views:

44

answers:

2

HI all,

I would like to call from my C# code, unamanaged library functions like presented below. There are two options and the both works. In this moment "Beep" function is simple and have no input/output parameters, pointers, references... I am wondering in more complex cases what would be adventages and disadvantage of both approches ?

Thanks, Milan.

    [DllImport("kernel32.dll")]
    public static extern bool Beep(uint iFreq, uint iDuration);
    public void TestBeep()
    {
        Beep(300, 3000);
    }

    internal delegate bool DelegBeep(uint iFreq, uint iDuration);
    [DllImport("kernel32.dll")]
    internal static extern IntPtr LoadLibrary(String dllname);
    [DllImport("kernel32.dll")]
    internal static extern IntPtr GetProcAddress(IntPtr hModule, String procName);
    public void BeepIt()
    {
        IntPtr kernel32 = LoadLibrary("Kernel32.dll");
        IntPtr procBeep = GetProcAddress(kernel32, "Beep");
        DelegBeep delegBeep = Marshal.GetDelegateForFunctionPointer(procBeep, typeof(DelegBeep)) as DelegBeep;
        delegBeep(50, 1000);//Hz,ms
    }
+3  A: 

Your second one is much more complicated than the first but achieves the same thing in this case.

If the name of the DLL and the name of the function are known at compile time, then stick with the first approach. If you don't know the name of the DLL and/or function until run time then the LoadLibary/GetProcAddress approach is your only option.

Tim Robinson
The name of dll I have to know in both cases right ? Otherwise LoadLibrary will return error, or maybe I can give full part to LoadLibrary function ?
milan
Right, but with `[DllImport]` you have to pass a constant string, whereas a call to `LoadLibrary` lets you determine the DLL name at runtime.
Tim Robinson
I try to comment out [DllImport("kernel32.dll")] in the second example but then I get exception that LoadLibray have no implementation. How I should call then LoadLibrary ?
milan
I don't follow... why are you commenting out the `[DllImport("kernel32.dll")]` next to `LoadLibrary`?
Tim Robinson
Yes I commented out all [DllImport("kernel32.dll")] because I thougt your idea is to use just LoadLibrary with correct library path, or I got it wrong ?
milan
Both pieces of code you posted are correct; you don't need to change them. Use either the first piece or the second piece; they both do the same thing. The first piece is simpler.
Tim Robinson
Hi Tim, if I want to dinamically load different libraries then the second code with LoadLibrary is better. But in that case I would need to have option to dinamically change path to the [DllImport("kernel32.dll")] attribute, how to do that ?
milan
No, leave `[DllImport("kernel32.dll")]` alone regardless. If you want to load libraries from different paths then change this line: `IntPtr kernel32 = LoadLibrary("Kernel32.dll");`
Tim Robinson
PS it would help if you could explain specifically what you're doing - I guess you don't really want to call the `Beep` function like this.
Tim Robinson
I would like to test dinamically different library and some of their functions but not to hard code library names and library functions. So with LoadLibrary I get dinamically library handle with GetProcAddress I get dinamically library function pointer but still it is not clear to me how without pre-defined delegate can I dinamically call library functions ? any idea ? In delegate I hardcode what are input/out types, but I would like to have in/out parameter(function declaration) also dinamically generated.
milan
It would be quite hard to have genuinely flexible delegate types; this applies to any language, not just C#. Assuming you already know the parameter types and return value, and none of the parameters are `out` or `ref`, you could make do with `System.Func` and `System.Action`.
Tim Robinson
+1  A: 

The P/Invoke marshaller finds an entrypoint in a DLL by using LoadLibrary() and GetProcAddress(). And knows how to convert a C# declaration to the equivalent of a delegate declaration.

Doing this yourself has no advantage beyond maybe a wee bit of efficiency. Which you'd better measure, it is no slamdunk.

Hans Passant