I am trying to load a Winamp input plugin and work with it in C#. According to the Winamp SDK, this is the proper way to load a 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 a 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 the line with LoadLibrary, an error (not exception) window is shown:
---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
Runtime Error!
Program: C:\Users\...
R6034
An application has made an attempt to load the C runtime library incorrectly.
Please contact the application's support team for more information.
---------------------------
OK
---------------------------
And hmod is null.
Apparently, the plugin tries to load msvcrt90.dll, but this error keeps showing even if I have it in the directory.
Problem solved, next one has arised.
Solved.
Add a manifest to your project. At the end of the manifest paste:
(there should already be a commented example
<dependency>)This will use the Microsoft.VC90.CRT that is in WinSxS. Go to the properties of your project, and check that in Application->Resources your Manifest is selected.
Now go in the properties of your project, and disable
Enable the Visual Studio hosting project.You'll need to put the
in_midi.dllin the same folder of your .exe .Now it should work.
For reference, I'm using:
If you need, I can pass you the whole project zipped.
For the second question... Sadly the function returns a pointer to a
struct. This is a problem in C#. If you only needed to read from that struct, it would be easy, but you have to modify it. You could use theMarshal.PtrToStructure+Marshal.StructureToPtr, but I don't think it would be a good idea (there are delegates and strings that need marshaling... I don't want to think what would happen). The last time I needed to do it, I did full manual marshalling:I've already put a setter for the functions that you'll need to implement.
Use it like:
Note the comment!