CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Feb 2000
    Posts
    149

    Callback functions

    Hello all,

    I'm having a devil of a time getting my callback procedure to function correctly. I have a C++ dll which performs file splitting, it's multi threaded, so I pass it the AddressOf MyCallBackFunction as one of the parameters so I can perform further processing when it is done. I keep getting an error stating that different calling conventions are being used, the value of ESP is not being saved properly, something like that. I'll post the code for the Split DLL first:


    #define _WIN32_WINNT 0x0400

    #include <windows.h>
    #include <stdlib.h>
    #include <string.h>
    #include <process.h>

    enum SplitTypes
    {
    binary,
    FIXEDWIDTH_ASCII,
    FIXEDWIDTH_UNIX,
    CSV_ASCII,
    CSV_UNIX,
    DBASEIII,
    }; // end enum


    //bool CleanThreadList(void);

    BOOL APIENTRY DllMain( HANDLE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
    {
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
    break;
    }; // end case
    case DLL_THREAD_ATTACH:
    {
    break;
    }; // end case
    case DLL_THREAD_DETACH:
    {
    break;
    }; // end case
    case DLL_PROCESS_DETACH:
    {
    break;
    }; // end case
    }; // end switch;
    return true;
    };

    //typedef long __stdcall SplitFinishedProc(void *prParameter1,

    typedef long __stdcall SplitFinishedProc(void *prParameter1,
    //typedef long PASCAL SplitFinishedProc(void *prParameter1,
    void *prParameter2,
    long &result);

    struct JobData
    {
    long SplitSize;
    char *BaseFile;
    char *DestinationPath;
    long Type;
    }; // end JobData struct

    struct InternalJobData
    {
    JobData *Data;
    void *Parameter1;
    void *Parameter2;
    SplitFinishedProc *SplitFinishedProc;
    HANDLE Thread;
    bool AbortFlag;
    }; // end InternalJobData struct

    struct ThreadDataNode
    {
    ThreadDataNode *Previous;
    InternalJobData *InternalData;
    ThreadDataNode *next;
    }; //BaseNode; // end ThreadDataNode struct

    class GlobalMemoryClassType
    {
    public:
    ThreadDataNode *AddThreadDataNode(InternalJobData *prInternalJobData);
    bool DeleteThreadDataNode(ThreadDataNode *prThreadDataNode);
    bool CleanThreadList(void);
    GlobalMemoryClassType();
    ~GlobalMemoryClassType();
    private:
    ThreadDataNode *BaseNode;

    } GlobalMemoryClass;


    GlobalMemoryClassType::GlobalMemoryClassType()
    {
    //MessageBox(null, "Initializing class!", "Check", MB_OK);
    // nothing!!
    };


    GlobalMemoryClassType::~GlobalMemoryClassType()
    {
    //bool result;

    //MessageBox(null, "Disposing!", "Check", MB_OK);

    //result = this->CleanThreadList();

    };

    ThreadDataNode *GlobalMemoryClassType::AddThreadDataNode(InternalJobData *prInternalJobData)
    {

    CRITICAL_SECTION *LocalCriticalSection = new CRITICAL_SECTION;
    InitializeCriticalSection(LocalCriticalSection);
    EnterCriticalSection(LocalCriticalSection);

    ThreadDataNode *ActualNode;
    ThreadDataNode *ReturnNode;

    ReturnNode = new ThreadDataNode;
    ReturnNode->next = null;
    ReturnNode->Previous = null;

    if (this->BaseNode == null)
    {
    this->BaseNode = ReturnNode;
    }
    else
    {
    ActualNode = this->BaseNode;
    while (ActualNode->next != null)
    {
    ActualNode = ActualNode->next;
    }; // end while
    ActualNode->next = ReturnNode;
    ReturnNode ->Previous = ActualNode;
    }; // end if

    ReturnNode->InternalData = new InternalJobData;
    ReturnNode->InternalData->Data = new JobData;

    ReturnNode->InternalData->Data->BaseFile = new char[256];
    strcpy(ReturnNode->InternalData->Data->BaseFile, prInternalJobData->Data->BaseFile);

    ReturnNode->InternalData->Data->DestinationPath = new char[256];
    strcpy(ReturnNode->InternalData->Data->DestinationPath, prInternalJobData->Data->DestinationPath);

    ReturnNode->InternalData->Data->SplitSize = prInternalJobData->Data->SplitSize;
    ReturnNode->InternalData->Data->Type = prInternalJobData->Data->Type;

    ReturnNode->InternalData->Parameter1 = prInternalJobData->Parameter1;
    ReturnNode->InternalData->Parameter2 = prInternalJobData->Parameter2;
    ReturnNode->InternalData->SplitFinishedProc = prInternalJobData->SplitFinishedProc;
    ReturnNode->InternalData->AbortFlag = false;

    LeaveCriticalSection(LocalCriticalSection);

    DeleteCriticalSection(LocalCriticalSection);

    delete LocalCriticalSection;

    return (ReturnNode);
    }; // end AddThreadDataNode procedure

    bool GlobalMemoryClassType:eleteThreadDataNode(ThreadDataNode *prThreadDataNode)
    {
    CRITICAL_SECTION *LocalCriticalSection = new CRITICAL_SECTION;
    InitializeCriticalSection(LocalCriticalSection);
    EnterCriticalSection(LocalCriticalSection);

    bool LocalReturnValue = true;
    ThreadDataNode *PreviousNode;
    ThreadDataNode *NextNode;

    NextNode = prThreadDataNode->next;
    PreviousNode = prThreadDataNode->Previous;

    if (PreviousNode != null)
    {
    PreviousNode->next = NextNode;
    }; // end if

    if (NextNode != null)
    {
    NextNode->Previous = PreviousNode;
    }; // end if

    if (prThreadDataNode == this->BaseNode)
    {
    this->BaseNode = NextNode;
    }; // end if


    if (!CloseHandle(prThreadDataNode->InternalData->Thread))
    {
    LocalReturnValue = false;
    }; // end if


    delete [] (prThreadDataNode->InternalData->Data->BaseFile);
    delete [] (prThreadDataNode->InternalData->Data->DestinationPath);
    delete(prThreadDataNode->InternalData->Data);
    delete(prThreadDataNode->InternalData);
    delete(prThreadDataNode);

    LeaveCriticalSection(LocalCriticalSection);

    DeleteCriticalSection(LocalCriticalSection);

    delete LocalCriticalSection;

    return LocalReturnValue;

    }; // end DeleteThreadDataNode procedure

    bool GlobalMemoryClassType::CleanThreadList(void)
    {
    bool LocalReturnValue = true;
    ThreadDataNode *ActualNode;
    ThreadDataNode *SaveNode;

    CRITICAL_SECTION *LocalCriticalSection = new CRITICAL_SECTION;
    InitializeCriticalSection(LocalCriticalSection);

    while (this->BaseNode != null)
    {
    EnterCriticalSection(LocalCriticalSection);

    ActualNode = this->BaseNode;

    while (ActualNode != null)
    {
    SaveNode = ActualNode;
    ActualNode->InternalData->AbortFlag = true;
    ActualNode = ActualNode->next;
    };
    LeaveCriticalSection(LocalCriticalSection);
    };

    DeleteCriticalSection(LocalCriticalSection);

    // MessageBox(null, "Cleaned up!", "Check", MB_OK);

    return (LocalReturnValue);

    }; // end CleanThreadList

    DWORD WINAPI SplitInternal (void *prThreadDataNode)
    {
    ThreadDataNode *LocalThreadDataNode = new ThreadDataNode;
    long LocalReturnValue = true;
    HANDLE LocalBaseFileHandle;
    BY_HANDLE_FILE_INFORMATION *LocalByHandleFileInformation = new BY_HANDLE_FILE_INFORMATION;
    _int64 LocalBaseFileSize;

    long int LocalChunks;

    char *LocalDrive = new char[4];
    char *LocalPath = new char[256];
    char *LocalName = new char[256];
    char *LocalExtension = new char[256];

    char *LocalAppendName = new char[14];
    char *LocalSplitFile = new char[256];

    strcpy(LocalSplitFile, "");

    HANDLE LocalSplitFileHandle;

    unsigned long LocalSplitFilePosition;
    long LocalBufferSize;

    char *LocalReadBuffer = null;
    DWORD LocalBytesToRead = 0;
    DWORD LocalBytesRead = 0;

    char *LocalWriteBuffer = null;
    DWORD LocalBytesToWrite = 0;
    DWORD LocalBytesWritten = 0;

    char *LocalSaveBuffer = null;

    long LocalBaseBufferSize = (1024 * 100);

    char LocalDbaseBaseHeader[32]; // Standard DBase base header without field descriptions

    char *LocalDbaseHeader = null; // Full Header with field descriptions
    int LocalDbaseHeaderSize = 0;
    int LocalDbaseRecordSize = 0;
    long LocalDbaseRecordsThisChunk = 0;

    unsigned long LocalChunkSize = 0;

    unsigned long LocalEndOfRecordPosition = 0;

    bool LocalFinishedReading = false;

    memcpy(LocalThreadDataNode, prThreadDataNode, sizeof(ThreadDataNode));

    if (LocalThreadDataNode->InternalData->AbortFlag == true)
    {
    delete [] (LocalDrive);
    delete [] (LocalPath);
    delete [] (LocalName);
    delete [] (LocalExtension);
    delete [] (LocalAppendName);
    delete [] (LocalSplitFile);
    delete (LocalByHandleFileInformation);
    GlobalMemoryClass.DeleteThreadDataNode(LocalThreadDataNode);
    ExitThread(0);
    };

    if (LocalThreadDataNode->InternalData->Data == null)
    {
    LocalReturnValue = false;
    }
    else
    {
    LocalBufferSize = ((LocalBaseBufferSize) < (LocalThreadDataNode->InternalData->Data->SplitSize) ? (LocalBaseBufferSize) : (LocalThreadDataNode->InternalData->Data->SplitSize));
    LocalChunkSize = LocalThreadDataNode->InternalData->Data->SplitSize;

    LocalReadBuffer = new char[LocalBufferSize];
    LocalWriteBuffer = new char[LocalBufferSize];
    LocalSaveBuffer = new char[LocalBufferSize];

    if ((null == LocalReadBuffer) || (null == LocalWriteBuffer) || (null == LocalSaveBuffer))
    {
    if (null != LocalReadBuffer)
    delete [] (LocalReadBuffer);
    if (null != LocalWriteBuffer)
    delete [] (LocalWriteBuffer);
    if (null != LocalSaveBuffer)
    delete [] (LocalSaveBuffer);

    LocalReturnValue = false;
    }
    else
    {
    LocalBytesToRead = LocalBufferSize;
    LocalBaseFileHandle = CreateFile(LocalThreadDataNode->InternalData->Data->BaseFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
    if (LocalBaseFileHandle == null)
    {
    LocalReturnValue = false;
    }
    else
    {
    if (!GetFileInformationByHandle(LocalBaseFileHandle, LocalByHandleFileInformation))
    {
    LocalReturnValue = false;
    }
    else
    {
    LocalBaseFileSize = ((LocalByHandleFileInformation->nFileSizeHigh) * 4294967296) + LocalByHandleFileInformation->nFileSizeLow;
    LocalChunks = int(LocalBaseFileSize / LocalThreadDataNode->InternalData->Data->SplitSize) + ((LocalBaseFileSize % LocalThreadDataNode->InternalData->Data->SplitSize) == 0 ? 0 : 1);
    _splitpath(LocalThreadDataNode->InternalData->Data->BaseFile, LocalDrive, LocalPath, LocalName, LocalExtension);

    if (LocalThreadDataNode->InternalData->Data->Type == static_cast <long> (DBASEIII))
    {
    if (!ReadFile(LocalBaseFileHandle, LocalDbaseBaseHeader, sizeof(LocalDbaseBaseHeader), &LocalBytesRead, null))
    {
    MessageBox(null , "error reading Small Header", "Check", MB_OK);
    }
    else
    {
    if (LocalBytesRead != sizeof(LocalDbaseBaseHeader))
    {
    MessageBox(null, "The amount of readed bytes does not match the HeaderSize", "Check", MB_OK);
    }
    else
    {
    LocalDbaseHeaderSize = 0;
    LocalDbaseRecordSize = 0;
    memcpy(&LocalDbaseRecordSize, &LocalDbaseBaseHeader[10], 2);
    memcpy(&LocalDbaseHeaderSize, &LocalDbaseBaseHeader[8], 2);
    LocalChunkSize = (LocalChunkSize - 1) - ((LocalChunkSize - LocalDbaseHeaderSize) % LocalDbaseRecordSize) + 1; // - 1 to have for the EOF char
    if (LocalChunkSize <= 0)
    {
    MessageBox(null, "LocalChunkSize got smaller than 0", "Check", MB_OK);
    }
    else
    {
    LocalDbaseHeader = new char[LocalDbaseHeaderSize];
    SetFilePointer(LocalBaseFileHandle, 0, 0, FILE_BEGIN);
    if (GetLastError() != NO_ERROR)
    {
    MessageBox(null, "error repositioning the file", "Check", MB_OK);
    }
    else
    {
    if (!ReadFile(LocalBaseFileHandle, LocalDbaseHeader, LocalDbaseHeaderSize, &LocalBytesRead, null))
    {
    MessageBox(null , "error reading Header", "Check", MB_OK);
    }
    else
    {

    }; // end if
    }; // end if
    }; // end if
    }; // end if
    }; // end if
    }; // end if

    int i = 0;
    for(;
    {
    i++;
    if ((LocalThreadDataNode->InternalData->AbortFlag == true) ||
    (LocalReturnValue = false))
    {
    break;
    };
    strcpy(LocalSplitFile,"");
    if (null != LocalThreadDataNode->InternalData->Data->DestinationPath)
    {
    strcat(LocalSplitFile, LocalThreadDataNode->InternalData->Data->DestinationPath);
    }
    else
    {
    strcat(LocalSplitFile, LocalPath);
    }; // end if

    strcat(LocalSplitFile, "\\");
    strcat(LocalSplitFile, LocalName);
    strcat(LocalSplitFile, "-");
    strcat(LocalSplitFile, ltoa(i,LocalAppendName,10));
    strcat(LocalSplitFile, LocalExtension);

    if (strlen(LocalSplitFile) > 255)
    {
    MessageBox(null, itoa(strlen(LocalSplitFile), LocalAppendName, 10), "Check", MB_OK);
    MessageBox(null, "The split filename is longer than what the system can handle", "error", MB_OK);
    LocalReturnValue = false;
    break;
    };

    //LocalSplitFileHandle = CreateFile(LocalSplitFile, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL + FILE_FLAG_WRITE_THROUGH,0);
    LocalSplitFileHandle = CreateFile(LocalSplitFile, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,0);
    if (LocalSplitFileHandle == null)
    {
    LocalReturnValue = false;
    break;
    }
    else
    {
    LocalSplitFilePosition = 0;

    if (LocalDbaseHeaderSize != 0)
    {
    if (i < LocalChunks)
    {
    LocalDbaseRecordsThisChunk = ((LocalChunkSize - LocalDbaseHeaderSize) / LocalDbaseRecordSize);
    }
    else
    {
    LocalDbaseRecordsThisChunk = static_cast <long> ((LocalBaseFileSize - LocalDbaseHeaderSize - 1) % (LocalChunkSize - LocalDbaseHeaderSize)) / LocalDbaseRecordSize;
    }; // end if
    memcpy(&LocalDbaseHeader[4], &LocalDbaseRecordsThisChunk, sizeof(LocalDbaseRecordsThisChunk));
    if (!WriteFile(LocalSplitFileHandle, LocalDbaseHeader, LocalDbaseHeaderSize, &LocalBytesWritten, null))
    {
    LocalReturnValue = false;
    break;
    }
    else
    {
    LocalSplitFilePosition += LocalBytesWritten;
    }; // end if
    }; // end if

    for(;
    {
    memcpy(LocalReadBuffer, LocalSaveBuffer, LocalBytesToWrite);

    if (!ReadFile(LocalBaseFileHandle, LocalReadBuffer + LocalBytesToWrite, LocalBytesToRead - LocalBytesToWrite, &LocalBytesRead, null))
    {
    LocalReturnValue = false;
    break;
    }
    else
    {
    if ((LocalBytesRead + LocalBytesToWrite) == 0)
    {
    LocalFinishedReading = true;
    break;
    }
    else
    {
    if ((LocalSplitFilePosition + LocalBytesRead + LocalBytesToWrite) <= LocalChunkSize)
    {
    LocalEndOfRecordPosition = LocalBytesRead + LocalBytesToWrite;
    if ((LocalThreadDataNode->InternalData->Data->Type != static_cast <long> (binary)) &&
    (LocalThreadDataNode->InternalData->Data->Type != static_cast <long> (DBASEIII)))
    {
    for( ; LocalEndOfRecordPosition > 0 ; LocalEndOfRecordPosition--)
    {
    if (LocalReadBuffer[LocalEndOfRecordPosition - 1] == 10)
    {
    break;
    }; // end if
    }; // end for
    /*if (LocalEndOfRecordPosition <= 0) // This means the record is bigger than the split size
    {
    LocalReturnValue = false;
    break;
    };*/
    }
    else
    {
    LocalEndOfRecordPosition = LocalBytesRead + LocalBytesToWrite;
    }; // end if

    memcpy(LocalWriteBuffer, LocalReadBuffer, LocalEndOfRecordPosition);
    memcpy(LocalSaveBuffer, LocalReadBuffer + LocalEndOfRecordPosition, LocalBytesRead + LocalBytesToWrite - LocalEndOfRecordPosition);
    if (!WriteFile(LocalSplitFileHandle, LocalWriteBuffer, LocalEndOfRecordPosition, &LocalBytesWritten, null))
    {
    LocalReturnValue = false;
    break;
    }
    else
    {
    LocalSplitFilePosition += LocalBytesWritten;
    LocalBytesToWrite = LocalBytesRead + LocalBytesToWrite - LocalBytesWritten;
    }; // end if
    }
    else
    {
    LocalEndOfRecordPosition = (LocalChunkSize - LocalSplitFilePosition);

    if ((LocalThreadDataNode->InternalData->Data->Type != static_cast <long> (binary)) &&
    (LocalThreadDataNode->InternalData->Data->Type != static_cast <long> (DBASEIII)))
    {
    for( ; LocalEndOfRecordPosition > 0 ; LocalEndOfRecordPosition--)
    {
    if (LocalReadBuffer[LocalEndOfRecordPosition - 1] == 10)
    {
    break;
    }; // end if
    }; // end for
    /*if (LocalEndOfRecordPosition <= 0) // This means the record is bigger than the split size
    {
    LocalReturnValue = false;
    break;
    };*/
    }
    else
    {
    LocalEndOfRecordPosition = (LocalChunkSize - LocalSplitFilePosition);
    }; // end if

    memcpy(LocalWriteBuffer, LocalReadBuffer, LocalEndOfRecordPosition);
    memcpy(LocalSaveBuffer, LocalReadBuffer + LocalEndOfRecordPosition, LocalBytesRead + LocalBytesToWrite - LocalEndOfRecordPosition);
    if (!WriteFile(LocalSplitFileHandle, LocalWriteBuffer, LocalEndOfRecordPosition, &LocalBytesWritten, null))
    {
    LocalReturnValue = false;
    break;
    }
    else
    {
    LocalSplitFilePosition += LocalBytesWritten;
    LocalBytesToWrite = LocalBytesRead + LocalBytesToWrite - LocalBytesWritten;
    }; // end if
    break;
    }; // end if
    }; // end if
    }; // end if
    }; // end for
    }; // end if
    if (LocalThreadDataNode->InternalData->Data->Type == static_cast <long> (DBASEIII))
    {
    LocalWriteBuffer[0] = 0x1A; // Dbase file terminator
    if (!WriteFile(LocalSplitFileHandle, LocalWriteBuffer, 1, &LocalBytesWritten, null))
    {
    LocalReturnValue = false;
    break;
    }
    else
    {
    LocalSplitFilePosition += 1;
    }; // end if
    }; // end if

    if (!CloseHandle(LocalSplitFileHandle))
    {
    LocalReturnValue = false;
    break;
    }; // end if

    if (LocalFinishedReading == true)
    {
    break;
    };
    }; // end for
    }; // end if
    if (!CloseHandle(LocalBaseFileHandle))
    {
    LocalReturnValue = false;
    }; // end if
    }; // end if
    }; // end if

    delete[] LocalReadBuffer;
    delete[] LocalWriteBuffer;
    delete[] LocalSaveBuffer;
    }; // end if


    // MessageBox(null, "Check on finishing split", "Check", MB_OK);

    delete[] LocalDrive;
    delete[] LocalPath;
    delete[] LocalName;
    delete[] LocalExtension;
    delete[] LocalAppendName;
    // MessageBox(null, "Before deleting localsplitfile", "Check", MB_OK);
    delete[] LocalSplitFile;
    delete LocalByHandleFileInformation;


    // MessageBox(null, "After on finishing split", "Check", MB_OK);

    //if ((null != LocalThreadDataNode->InternalData->SplitFinishedProc) && (LocalThreadDataNode == false))
    if (null != LocalThreadDataNode->InternalData->SplitFinishedProc)
    {
    LocalThreadDataNode->InternalData->SplitFinishedProc(LocalThreadDataNode->InternalData->Parameter1, LocalThreadDataNode->InternalData->Parameter2, LocalReturnValue);
    }; // end if

    GlobalMemoryClass.DeleteThreadDataNode(LocalThreadDataNode);

    ExitThread(LocalReturnValue);

    return (LocalReturnValue);

    }; // end SplitFileInternal procedure


    //extern "C" bool __declspec (dllexport) PASCAL Split (JobData *prJobData,
    extern "C" bool __declspec (dllexport) __stdcall Split (JobData *prJobData,

    SplitFinishedProc *prSplitFinishedProc,
    void *prParameter1,
    void *prParameter2)
    {

    bool LocalReturnValue = true;
    ThreadDataNode *LocalThreadDataNode;
    HANDLE LocalThread;
    DWORD LocalThreadId;


    InternalJobData *LocalInternalJobData = new InternalJobData;

    LocalInternalJobData->Data = prJobData;
    LocalInternalJobData->Parameter1 = prParameter1;
    LocalInternalJobData->Parameter2 = prParameter2;
    LocalInternalJobData->SplitFinishedProc = prSplitFinishedProc;

    LocalThreadDataNode = GlobalMemoryClass.AddThreadDataNode(LocalInternalJobData);
    if (null == LocalThreadDataNode)
    {
    LocalReturnValue = false;
    }
    else
    {
    LocalThread = CreateThread(null, 0, SplitInternal, LocalThreadDataNode, 0, &LocalThreadId);
    if (null == LocalThread)
    {
    GlobalMemoryClass.DeleteThreadDataNode(LocalThreadDataNode);
    LocalReturnValue = false;
    }
    else
    {
    LocalThreadDataNode->InternalData->Thread = LocalThread;
    }; // end if
    }; // end if

    delete (LocalInternalJobData);

    return (LocalReturnValue);
    }; // end Split procedure




    Here is how I call the dll:


    public Type JobData
    SplitSize as Long
    BaseFile as string
    DestinationPath as string
    Type as Long
    End Type

    Data.SplitSize = lngCDSplitSize '630 mbs
    Data.DestinationPath = CDFILEDIRECTORY 'local dir
    Data.BaseFile = "C:\test\0001275183.txt"
    Data.Type = FIXEDWIDTH_ASCII

    Split Data, AddressOf MyCallbackFunction, 0, 0






    Then I have a module included in the project with my callback procedure:


    public Sub MyCallBackFunction(byval lng1 as Long, byval lng2 as Long, byval lng3 as Long)
    on error resume next
    DoThis
    ThenDoThis
    NextDoThis
    End Sub





    As you can see in the C code, I have tried both __stdcall and PASCAL calling conventions, I really don't know what I am doing wrong. If I eliminate accepting parameters in my callback function, the file splitting works but not everything is done in my callback function. If I leave the parameters as they are now I get the file split, and then the program crashes when it trys to call back.

    Can anyone shed some light on this?

    Thanks,
    Sean


  2. #2
    Join Date
    Jul 2000
    Location
    Milano, Italy
    Posts
    7,726

    Re: Callback functions

    Maybe this is not the point - I am not a C developer, nor a callBack expert, so
    forgive my ignorance- but I think in a callBack function you should name the
    function matching cases:
    in example you wrote:
    Split Data, AddressOf MyCallbackFunction, 0, 0
    and then:
    public Sub MyCallBackFunction
    the "B" in name is different. I have seen public in lowercase, so it seems you
    rewrote the whole instead of copying it, and the typo may not exist in your
    code. However, it may be a good idea to check...

    Special thanks to Lothar "the Great" Haensler, Tom Archer, Chris Eastwood, TCartwright, Bruno Paris, Dr_Michael
    and all the other wonderful people who made and make Codeguru a great place.
    Come back soon, you Gurus.

    The Rater
    ...at present time, using mainly Net 4.0, Vs 2010



    Special thanks to Lothar "the Great" Haensler, Chris Eastwood , dr_Michael, ClearCode, Iouri and
    all the other wonderful people who made and make Codeguru a great place.
    Come back soon, you Gurus.

  3. #3
    Join Date
    Dec 1999
    Location
    Dublin, Ireland
    Posts
    1,173

    Re: Callback functions

    In order to be certain, I'd need your function's TypeDef i.e.:

    typedef LRESULT (CALLBACK* MyCallbackProc)(lPar1, lPar2, lPar3, lPar4);




    However, the most obvious thing at this stage is that you have called it a callback function but passed it a subroutine.
    You can only do this if the typedef is:

    typedef VOID (CALLBACK* MyCallbackProc)...




    Otherwise change the VB code to:

    public Function MyCallbackProc(byval lPar1 as long, byval lpar2 as Long, byval lPar3 as Long, byval lPar4 as Long) as Long

    '...yadda

    End Function




    HTH,
    Duncan

    -------------------------------------------------
    Ex. Datis: Duncan Jones
    Merrion Computing Ltd
    http://www.merrioncomputing.com
    Check out the new downloads - ImageMap.ocx is the VB control that emulates an HTML image map, EventVB.OCX for adding new events to your VB form and adding System Tray support simply, MCL Hotkey for implemenmting system-wide hotkeys in your application...all with source code included.
    '--8<-----------------------------------------
    NEW -The printer usage monitoring application
    '--8<------------------------------------------

  4. #4
    Join Date
    Jul 2000
    Location
    Milano, Italy
    Posts
    7,726

    Re: Hi!

    Nice to see you here. A pity I am already out of votes...
    &lt;Excelent!&gt; should be setted here.

    Special thanks to Lothar "the Great" Haensler, Tom Archer, Chris Eastwood, TCartwright, Bruno Paris, Dr_Michael
    and all the other wonderful people who made and make Codeguru a great place.
    Come back soon, you Gurus.

    The Rater
    ...at present time, using mainly Net 4.0, Vs 2010



    Special thanks to Lothar "the Great" Haensler, Chris Eastwood , dr_Michael, ClearCode, Iouri and
    all the other wonderful people who made and make Codeguru a great place.
    Come back soon, you Gurus.

  5. #5
    Join Date
    Dec 1999
    Location
    Dublin, Ireland
    Posts
    1,173

    Re: Hi!

    I'm just cultivating some C programmer contacts. I have finally realised that the global subclassing side of the EventVB.dll cannot be done in VB alone so I'm off to write me a C dll.



    -------------------------------------------------
    Ex. Datis: Duncan Jones
    Merrion Computing Ltd
    http://www.merrioncomputing.com
    Check out the new downloads - ImageMap.ocx is the VB control that emulates an HTML image map, EventVB.OCX for adding new events to your VB form and adding System Tray support simply, MCL Hotkey for implemenmting system-wide hotkeys in your application...all with source code included.
    '--8<-----------------------------------------
    NEW -The printer usage monitoring application
    '--8<------------------------------------------

  6. #6
    Join Date
    Jul 2000
    Location
    Milano, Italy
    Posts
    7,726

    Re: EventVb

    I was afraid of it. It seemed too much like a dreeam to have low level functions in Vb... Well, let me know when I can download the new version...
    ;-)
    Have a nice day, Duncan

    Special thanks to Lothar "the Great" Haensler, Tom Archer, Chris Eastwood, TCartwright, Bruno Paris, Dr_Michael
    and all the other wonderful people who made and make Codeguru a great place.
    Come back soon, you Gurus.

    The Rater
    ...at present time, using mainly Net 4.0, Vs 2010



    Special thanks to Lothar "the Great" Haensler, Chris Eastwood , dr_Michael, ClearCode, Iouri and
    all the other wonderful people who made and make Codeguru a great place.
    Come back soon, you Gurus.

  7. #7
    Join Date
    Dec 1999
    Location
    Dublin, Ireland
    Posts
    1,173

    Re: EventVb

    Well, the current release candidate (1.1.5) does an awful lot. I need to find out how to list the existing Named Pipes on a system before I "announce" it but the code added for getting the hardware profile and for enumerating the print jobs seems to be very robust.

    Unfortunately I now have to do some paid work before I can return to it...an overdraft is a cruel master.

    -------------------------------------------------
    Ex. Datis: Duncan Jones
    Merrion Computing Ltd
    http://www.merrioncomputing.com
    Check out the new downloads - ImageMap.ocx is the VB control that emulates an HTML image map, EventVB.OCX for adding new events to your VB form and adding System Tray support simply, MCL Hotkey for implemenmting system-wide hotkeys in your application...all with source code included.
    '--8<-----------------------------------------
    NEW -The printer usage monitoring application
    '--8<------------------------------------------

  8. #8
    Join Date
    Feb 2000
    Posts
    149

    Re: EventVb

    Thanks for the replies guys...I was finally able to get it working by changing what I try to do in my callback function. I now simply change the value of a boolean in the callback, while on the form a timer checks the value of that boolean, and acts when it's value is changed. I think perhaps the way I was doing it before, my split thread didn't end before calling the new procedures. Not sure, but it's working so far... 8-)

    Thanks again,

    Sean


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured