i trying load winamp input plugin , work in c#. according winamp sdk, proper way load plugin:
in_mp3_lib = loadlibraryw(path); if (in_mp3_lib) { plugingetter plugingetter = (plugingetter)getprocaddress(in_mp3_lib, "winampgetinmodule2"); if (plugingetter) { in_mp3 = plugingetter(); } }
so i've created similar code in c#:
[dllimport("kernel32", setlasterror=true, charset=charset.unicode)] static extern intptr loadlibrary(string lpfilename); [dllimport("kernel32", charset=charset.ansi, exactspelling=true, setlasterror=true)] static extern intptr getprocaddress(intptr hmodule, string procname); delegate intptr plugingetter(); intptr hmod = loadlibrary("in_midi.dll"); var getmod = (plugingetter)marshal.getdelegateforfunctionpointer(getprocaddress(hmod, "winampgetinmodule2"), typeof(plugingetter)); intptr modptr = getmod();
however, on line loadlibrary
, error (not exception) window shown:
--------------------------- microsoft visual c++ runtime library --------------------------- runtime error! program: c:\users\... r6034 application has made attempt load c runtime library incorrectly. please contact application's support team more information. --------------------------- ok ---------------------------
and hmod
null.
apparently, plugin tries load msvcrt90.dll, error keeps showing if have in directory.
problem solved, next one has arised.
solved.
add manifest project. @ end of manifest paste:
<dependency> <dependentassembly> <assemblyidentity type="win32" name="microsoft.vc90.crt" version="9.0.30729.4926" processorarchitecture="x86" publickeytoken="1fc8b3b9a1e18e3b" /> </dependentassembly> </dependency>
(there should commented example <dependency>
)
this use microsoft.vc90.crt in winsxs. go properties of project, , check in application->resources manifest selected.
now go in properties of project, , disable enable visual studio hosting project
.
you'll need put in_midi.dll
in same folder of .exe .
now should work.
for reference, i'm using:
class program { [dllimport("kernel32", callingconvention = callingconvention.winapi, charset = charset.unicode, entrypoint = "loadlibraryw", exactspelling = true, setlasterror = true)] static extern intptr loadlibrary(string lpfilename); [dllimport("kernel32", callingconvention = callingconvention.winapi, charset = charset.ansi, exactspelling = true, setlasterror = true)] static extern intptr getprocaddress(intptr hmodule, string procname); [unmanagedfunctionpointer(callingconvention.cdecl)] delegate intptr plugingetter(); static void main(string[] args) { intptr hmod = loadlibrary("in_midi.dll"); if (hmod == intptr.zero) { throw new win32exception(); } intptr proc = getprocaddress(hmod, "winampgetinmodule2"); if (proc == intptr.zero) { throw new win32exception(); } plugingetter getmod = (plugingetter)marshal.getdelegateforfunctionpointer(proc, typeof(plugingetter)); intptr modptr = getmod(); if (modptr == intptr.zero) { throw new win32exception(); } console.writeline("success"); } }
if need, can pass whole project zipped.
for second question... sadly function returns pointer struct
. problem in c#. if needed read struct, easy, have modify it. use marshal.ptrtostructure
+ marshal.structuretoptr
, don't think idea (there delegates , strings need marshaling... don't want think happen). last time needed it, did full manual marshalling:
[structlayout(layoutkind.sequential)] public class in_module //ported in2.h in winamp sdk, struct size 152 { [dllimport("kernel32", callingconvention = callingconvention.winapi, charset = charset.unicode, entrypoint = "loadlibraryw", exactspelling = true, setlasterror = true)] private static extern intptr loadlibrary(string lpfilename); [dllimport("kernel32", callingconvention = callingconvention.winapi, charset = charset.ansi, exactspelling = true, setlasterror = true)] private static extern intptr getprocaddress(intptr hmodule, string procname); private static readonly int offsetofmethodtable = sizeof(int) + intptr.size + intptr.size + intptr.size + intptr.size + sizeof(int) + sizeof(int); intptr ptr; public void loadmidimodule() { intptr hmod = loadlibrary("in_midi.dll"); if (hmod == intptr.zero) { throw new win32exception(); } intptr proc = getprocaddress(hmod, "winampgetinmodule2"); if (proc == intptr.zero) { throw new win32exception(); } plugingetter getmod = (plugingetter)marshal.getdelegateforfunctionpointer(proc, typeof(plugingetter)); ptr = getmod(); if (ptr == intptr.zero) { throw new exception(); } hdllinstance = hmod; config = getdelegate<configfunc>(0 * intptr.size); = getdelegate<abountfunc>(1 * intptr.size); init = getdelegate<initfunc>(2 * intptr.size); quit = getdelegate<quitfunc>(3 * intptr.size); getfileinfo = getdelegate<getfileinfofunc>(4 * intptr.size); infobox = getdelegate<infoboxfunc>(5 * intptr.size); isourfile = getdelegate<isourfilefunc>(6 * intptr.size); play = getdelegate<playfunc>(7 * intptr.size); pause = getdelegate<pausefunc>(8 * intptr.size); unpause = getdelegate<unpausefunc>(9 * intptr.size); ispaused = getdelegate<ispausedfunc>(10 * intptr.size); stop = getdelegate<stopfunc>(11 * intptr.size); getlength = getdelegate<getlengthfunc>(12 * intptr.size); getoutputtime = getdelegate<getoutputtimefunc>(13 * intptr.size); setoutputtime = getdelegate<setoutputtimefunc>(14 * intptr.size); setvolume = getdelegate<setvolumefunc>(15 * intptr.size); setpan = getdelegate<setpanfunc>(16 * intptr.size); savsainit = getdelegate<savsainitfunc>(17 * intptr.size); savsadeinit = getdelegate<savsadeinitfunc>(18 * intptr.size); saaddpcmdata = getdelegate<saaddpcmdatafunc>(19 * intptr.size); sagetmode = getdelegate<sagetmodefunc>(20 * intptr.size); saadd = getdelegate<saaddfunc>(21 * intptr.size); vsaaddpcmdata = getdelegate<vsaaddpcmdatafunc>(22 * intptr.size); vsagetmode = getdelegate<vsagetmodefunc>(23 * intptr.size); vsaadd = getdelegate<vsaaddfunc>(24 * intptr.size); vsasetinfo = getdelegate<vsasetinfofunc>(25 * intptr.size); dsp_isactive = getdelegate<dsp_isactivefunc>(26 * intptr.size); dsp_dosamples = getdelegate<dsp_dosamplesfunc>(27 * intptr.size); eqset = getdelegate<eqsetfunc>(28 * intptr.size); setinfo = getdelegate<setinfofunc>(29 * intptr.size); } private tdelegate getdelegate<tdelegate>(int offset) { intptr ptr = marshal.readintptr(ptr, offsetofmethodtable + offset); if (ptr == intptr.zero) { return default(tdelegate); } return (tdelegate)(object)marshal.getdelegateforfunctionpointer(ptr, typeof(tdelegate)); } private void setdelegate<tdelegate>(tdelegate del, ref tdelegate field, int offset) { field = del; intptr ptr = marshal.getfunctionpointerfordelegate((delegate)(object)del); marshal.writeintptr(ptr, offsetofmethodtable + offset, ptr); } public int version { { return marshal.readint32(ptr, 0); } } public string description { { return marshal.ptrtostringansi(marshal.readintptr(ptr, sizeof(int))); } } public intptr hmainwindow { { return marshal.readintptr(ptr, sizeof(int) + intptr.size); } set { marshal.writeintptr(ptr, sizeof(int) + intptr.size, value); } } public intptr hdllinstance { { return marshal.readintptr(ptr, sizeof(int) + intptr.size + intptr.size); } set { marshal.writeintptr(ptr, sizeof(int) + intptr.size + intptr.size, value); } } public string fileextensions { { return marshal.ptrtostringansi(marshal.readintptr(ptr, sizeof(int) + intptr.size + intptr.size + intptr.size)); } } public int is_seekable { { return marshal.readint32(ptr, sizeof(int) + intptr.size + intptr.size + intptr.size + intptr.size); } } public int usesoutputplug { { return marshal.readint32(ptr, sizeof(int) + intptr.size + intptr.size + intptr.size + intptr.size + sizeof(int)); } } private configfunc config; public configfunc config { { return config; } } private abountfunc about; public abountfunc { { return about; } } private initfunc init; public initfunc init { { return init; } } private quitfunc quit; public quitfunc quit { { return quit; } } private getfileinfofunc getfileinfo; public getfileinfofunc getfileinfo { { return getfileinfo; } } private infoboxfunc infobox; public infoboxfunc infobox { { return infobox; } } private isourfilefunc isourfile; public isourfilefunc isourfile { { return isourfile; } } private playfunc play; public playfunc play { { return play; } } private pausefunc pause; public pausefunc pause { { return pause; } } private unpausefunc unpause; public unpausefunc unpause { { return unpause; } } private ispausedfunc ispaused; public ispausedfunc ispaused { { return ispaused; } } private stopfunc stop; public stopfunc stop { { return stop; } } private getlengthfunc getlength; public getlengthfunc getlength { { return getlength; } } private getoutputtimefunc getoutputtime; public getoutputtimefunc getoutputtime { { return getoutputtime; } } private setoutputtimefunc setoutputtime; public setoutputtimefunc setoutputtime { { return setoutputtime; } } private setvolumefunc setvolume; public setvolumefunc setvolume { { return setvolume; } } private setpanfunc setpan; public setpanfunc setpan { { return setpan; } } private savsainitfunc savsainit; public savsainitfunc savsainit { { return savsainit; } set { setdelegate(value, ref savsainit, 17 * intptr.size); } } private savsadeinitfunc savsadeinit; public savsadeinitfunc savsadeinit { { return savsadeinit; } set { setdelegate(value, ref savsadeinit, 18 * intptr.size); } } private saaddpcmdatafunc saaddpcmdata; public saaddpcmdatafunc saaddpcmdata { { return saaddpcmdata; } set { setdelegate(value, ref saaddpcmdata, 19 * intptr.size); } } private sagetmodefunc sagetmode; public sagetmodefunc sagetmode { { return sagetmode; } set { setdelegate(value, ref sagetmode, 20 * intptr.size); } } private saaddfunc saadd; public saaddfunc saadd { { return saadd; } set { setdelegate(value, ref saadd, 21 * intptr.size); } } private vsaaddpcmdatafunc vsaaddpcmdata; public vsaaddpcmdatafunc vsaaddpcmdata { { return vsaaddpcmdata; } set { setdelegate(value, ref vsaaddpcmdata, 22 * intptr.size); } } private vsagetmodefunc vsagetmode; public vsagetmodefunc vsagetmode { { return vsagetmode; } set { setdelegate(value, ref vsagetmode, 23 * intptr.size); } } private vsaaddfunc vsaadd; public vsaaddfunc vsaadd { { return vsaadd; } set { setdelegate(value, ref vsaadd, 24 * intptr.size); } } private vsasetinfofunc vsasetinfo; public vsasetinfofunc vsasetinfo { { return vsasetinfo; } set { setdelegate(value, ref vsasetinfo, 25 * intptr.size); } } private dsp_isactivefunc dsp_isactive; public dsp_isactivefunc dsp_isactive { { return dsp_isactive; } set { setdelegate(value, ref dsp_isactive, 26 * intptr.size); } } private dsp_dosamplesfunc dsp_dosamples; public dsp_dosamplesfunc dsp_dosamples { { return dsp_dosamples; } set { setdelegate(value, ref dsp_dosamples, 27 * intptr.size); } } private eqsetfunc eqset; public eqsetfunc eqset { { return eqset; } } private setinfofunc setinfo; public setinfofunc setinfo { { return setinfo; } set { setdelegate(value, ref setinfo, 29 * intptr.size); } } public intptr outmod { { return marshal.readintptr(ptr, offsetofmethodtable + 30 * intptr.size); } } [unmanagedfunctionpointer(callingconvention.cdecl)] private delegate intptr plugingetter(); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void configfunc(intptr hwndparent); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void abountfunc(intptr hwndparent); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void initfunc(); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void quitfunc(); [unmanagedfunctionpointer(callingconvention.cdecl, charset = charset.ansi)] public delegate void getfileinfofunc(string file, string title, out int length_in_ms); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate int infoboxfunc(string file, intptr hwndparent); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate int isourfilefunc(string fn); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate int playfunc(string fn); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void pausefunc(); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void unpausefunc(); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate int ispausedfunc(); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void stopfunc(); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate int getlengthfunc(); // length in ms [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate int getoutputtimefunc(); // returns current output time in ms. (usually returns outmod->getoutputtime() [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void setoutputtimefunc(int time_in_ms); // seeks point in stream (in ms). signal thread seek, seeks , calls outmod->flush().. [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void setvolumefunc(int volume); // 0 255.. call outmod->setvolume [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void setpanfunc(int pan); // -127 127.. call outmod->setpan [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void savsainitfunc(int maxlatency_in_ms, int srate); // call once in play(). maxlatency_in_ms should value returned outmod->open() [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void savsadeinitfunc(); // call in stop() [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void saaddpcmdatafunc(intptr pcmdata, int nch, int bps, int timestamp); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate int sagetmodefunc(); // gets csa (the current type (4=ws,2=osc,1=spec)) [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate int saaddfunc(intptr data, int timestamp, int csa); // sets spec data, filled in winamp [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void vsaaddpcmdatafunc(intptr pcmdata, int nch, int bps, int timestamp); // sets vis data directly pcm data [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate int vsagetmodefunc(out int specnch, out int wavench); // use figure out give vsaadd [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate int vsaaddfunc(intptr data, int timestamp); // filled in winamp, called plug-in [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void vsasetinfofunc(int srate, int nch); // <-- correct (benski, dec 2005).. old declaration had params backwards [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate int dsp_isactivefunc(); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate int dsp_dosamplesfunc(ref short samples, int numsamples, int bps, int nch, int srate); [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void eqsetfunc(int on, byte[] data, int preamp); // 0-64 each, 31 +0, 0 +12, 63 -12. nothing ignore. [unmanagedfunctionpointer(callingconvention.cdecl)] public delegate void setinfofunc(int bitrate, int srate, int stereo, int synched); // if -1, changes ignored? :) }
i've put setter functions you'll need implement.
use like:
var mod = new in_module(); mod.loadmidimodule(); //var form = new form1(); // doesn't work, looking @ // http://dolphin-emu.googlecode.com/svn-history/r3174/trunk/externals/musicmod/player/src/inputplugin.cpp // seems plugins try hook windowproc. // i'm not sure if ok in winforms //mod.hmainwindow = form.handle; mod.init(); // note have implement: //savsainit //savsadeinit //saaddpcmdata //sagetmode //saadd //vsaaddpcmdata //vsagetmode //vsaadd //vsasetinfo //dsp_dosamples //dsp_isactive //setinfo
note comment!
Comments
Post a Comment