I'm trying to convert a C structure that include function pointer into a VB.Net structure that contain delegates. (Only .Net 2.0 and 3.0 users should attempt this.) When I call a function in an unmanaged dll that fills the structure, I get the following error (nontrapable exception):
Can anybody tell me how I got my delegate definitions or signatures messed up?Code:InvalidFunctionPointerInDelegate was detected Message: Invalid function pointer 0xb6390c91 was passed into the runtime to be converted to a delegate. Passing in invalid function pointers to be converted to delegates can cause crashes, corruption or data loss.
Original structure:
Translated to vb.netCode:typedef struct { int version; // module type (IN_VER) char *description; // description of module, with version string HWND hMainWindow; // winamp's main window (filled in by winamp) HINSTANCE hDllInstance; // DLL instance handle (Also filled in by winamp) char *FileExtensions; // "mp3\0Layer 3 MPEG\0mp2\0Layer 2 MPEG\0mpg\0Layer 1 MPEG\0" // May be altered from Config, so the user can select what they want int is_seekable; // is this stream seekable? int UsesOutputPlug; // does this plug-in use the output plug-ins? (musn't ever change, ever :) void (*Config)(HWND hwndParent); // configuration dialog void (*About)(HWND hwndParent); // about dialog void (*Init)(); // called at program init void (*Quit)(); // called at program quit void (*GetFileInfo)(char *file, char *title, int *length_in_ms); // if file == NULL, current playing is used int (*InfoBox)(char *file, HWND hwndParent); int (*IsOurFile)(char *fn); // called before extension checks, to allow detection of mms://, etc // playback stuff int (*Play)(char *fn); // return zero on success, -1 on file-not-found, some other value on other (stopping winamp) error void (*Pause)(); // pause stream void (*UnPause)(); // unpause stream int (*IsPaused)(); // ispaused? return 1 if paused, 0 if not void (*Stop)(); // stop (unload) stream // time stuff int (*GetLength)(); // get length in ms int (*GetOutputTime)(); // returns current output time in ms. (usually returns outMod->GetOutputTime() void (*SetOutputTime)(int time_in_ms); // seeks to point in stream (in ms). Usually you signal yoru thread to seek, which seeks and calls outMod->Flush().. // volume stuff void (*SetVolume)(int volume); // from 0 to 255.. usually just call outMod->SetVolume void (*SetPan)(int pan); // from -127 to 127.. usually just call outMod->SetPan // in-window builtin vis stuff void (*SAVSAInit)(int maxlatency_in_ms, int srate); // call once in Play(). maxlatency_in_ms should be the value returned from outMod->Open() // call after opening audio device with max latency in ms and samplerate void (*SAVSADeInit)(); // call in Stop() // simple vis supplying mode void (*SAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); // sets the spec data directly from PCM data // quick and easy way to get vis working :) // needs at least 576 samples :) // advanced vis supplying mode, only use if you're cool. Use SAAddPCMData for most stuff. int (*SAGetMode)(); // gets csa (the current type (4=ws,2=osc,1=spec)) // use when calling SAAdd() void (*SAAdd)(void *data, int timestamp, int csa); // sets the spec data, filled in by winamp // vis stuff (plug-in) // simple vis supplying mode void (*VSAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); // sets the vis data directly from PCM data // quick and easy way to get vis working :) // needs at least 576 samples :) // advanced vis supplying mode, only use if you're cool. Use VSAAddPCMData for most stuff. int (*VSAGetMode)(int *specNch, int *waveNch); // use to figure out what to give to VSAAdd void (*VSAAdd)(void *data, int timestamp); // filled in by winamp, called by plug-in // call this in Play() to tell the vis plug-ins the current output params. void (*VSASetInfo)(int nch, int srate); // dsp plug-in processing: // (filled in by winamp, called by input plug) // returns 1 if active (which means that the number of samples returned by dsp_dosamples // could be greater than went in.. Use it to estimate if you'll have enough room in the // output buffer int (*dsp_isactive)(); // returns number of samples to output. This can be as much as twice numsamples. // be sure to allocate enough buffer for samples, then. int (*dsp_dosamples)(short int *samples, int numsamples, int bps, int nch, int srate); // eq stuff void (*EQSet)(int on, char data[10], int preamp); // 0-64 each, 31 is +0, 0 is +12, 63 is -12. Do nothing to ignore. // info setting (filled in by winamp) void (*SetInfo)(int bitrate, int srate, int stereo, int synched); // if -1, changes ignored? :) Out_Module *outMod; // filled in by winamp, optionally used :) } In_Module;
VB Code:
<StructLayout(LayoutKind.Sequential)> _ Structure InModule Public version As Integer Public description As String Public hMainWindow As IntPtr Public hDllInstance As IntPtr Public FileExtensions As String Public is_seekable As Integer Public UsesOutputPlug As Integer Public Delegate Sub ConfigPTR(ByVal hwndParent As IntPtr) Public Config As ConfigPTR Public Delegate Sub AboutPTR(ByVal hwndParent As IntPtr) Public About As AboutPTR Public Delegate Sub InitPTR() Public Init As InitPTR Public Delegate Sub QuitPTR() Public Quit As QuitPTR Public Delegate Sub GetFileInfoPTR(ByRef file As String, ByRef title As String, ByRef lenght_in_ms As Integer) Public GetFileInfo As GetFileInfoPTR Public Delegate Function InfoBoxPTR(ByRef file As String, ByVal hwndParent As IntPtr) As Integer Public InfoBox As InfoBoxPTR Public Delegate Function IsOurFilePTR(ByRef fn As String) As Integer Public IsOurFile As IsOurFilePTR '//Playback stuff Public Delegate Function PlayPTR(ByRef fn As String) As Integer Public Play As PlayPTR Public Delegate Sub PausePTR() Public Pause As PausePTR Public Delegate Sub UnPausePTR() Public UnPause As UnPausePTR Public Delegate Function IsPausedPTR() As Integer Public IsPaused As IsPausedPTR Public Delegate Sub StopPTR() Public [Stop] As StopPTR '//Time stuff Public Delegate Function GetLengthPTR() As Integer Public GetLength As GetLengthPTR Public Delegate Function GetOutputTimePTR() As Integer Public GetOutputTime As GetOutputTimePTR Public Delegate Sub SetOutputTimePTR(ByVal time_in_ms As Integer) Public SetOutputTime As SetOutputTimePTR '//Volume stuff Public Delegate Sub SetVolumePTR(ByVal volume As Integer) Public SetVolume As SetVolumePTR Public Delegate Sub SetPanPTR(ByVal pan As Integer) Public SetPan As SetPanPTR '//In-window builtin vis stuff Public Delegate Sub SAVSAInitPTR(ByVal maxlatency_in_ms As Integer, ByVal srate As Integer) Public SAVSAInit As SAVSAInitPTR Public Delegate Sub SAVSADeInitPTR() Public SAVSADeInit As SAVSADeInitPTR '//Simple vis supplying mode Public Delegate Sub SAAddPCMDataPTR(ByRef PCMData As Byte(), ByVal nch As Integer, ByVal bps As Integer, ByVal timestamp As Integer) Public SAAddPCMData As SAAddPCMDataPTR '//Advanced vis supplying mode Public Delegate Function SAGetModePTR() As Integer Public SAGetMode As SAGetModePTR Public Delegate Sub SAAddPTR(ByRef data As Byte(), ByVal timestamp As Integer, ByVal csa As Integer) Public SAAdd As SAAddPTR '//vis stuff (plug-in) '//simple vis supplying mode Public Delegate Sub VSAAddPCMDataPTR(ByRef PCMData As Byte(), ByVal nch As Integer, ByVal bps As Integer, ByVal timestamp As Integer) Public VSAAddPCMData As VSAAddPCMDataPTR '//advanced vis supplying mode Public Delegate Function VSAGetModePTR(ByRef specNch As Integer, ByRef waveNch As Integer) As Integer Public VSAGetMode As VSAGetModePTR Public Delegate Sub VSAAddPTR(ByRef data As Byte(), ByVal timestamp As Integer) Public VSAAdd As VSAAddPTR Public Delegate Sub VSASetInfoPTR(ByVal nch As Integer, ByVal srate As Integer) Public VSASetInfo As VSASetInfoPTR '//dsp plug-in processing: '//(filled in by winamp, called by input plug) Public Delegate Function dsp_isactivePTR() As Integer Public dsp_isactive As dsp_isactivePTR Public Delegate Function dsp_dosamplesPTR(ByRef samples As Short, ByVal numsamples As Integer, ByVal bps As Integer, ByVal nch As Integer, ByVal srate As Integer) As Integer Public dsp_dosamples As dsp_dosamplesPTR '//eq stuff Public Delegate Sub EQSetPTR(ByVal [on] As Integer, ByVal data As Byte(), ByVal preamp As Integer) 'data is limited to 10 elements Public EQSet As EQSetPTR '//info setting Public Delegate Sub SetInfoPTR(ByVal bitrate As Integer, ByVal srate As Integer, ByVal stereo As Integer, ByVal synched As Integer) Public SetInfo As SetInfoPTR Public Out_Mod As WinampOutputPlugin.OutModule End Structure
Let me know if more information is required.


Reply With Quote