4

I am writing a C# binding for an unmanaged C dll.

The dll provides 5 hooks to return several data:

typedef void (*t_libpd_printhook)(const char *recv);

and exports a field like:

 EXTERN t_libpd_printhook libpd_printhook;

now i was using Interop Assistant to generate the binding code, which gave me just a delegate definition:

public delegate void t_libpd_printhook([In] [MarshalAs(UnmanagedType.LPStr)] string recv);

So is there some magic Interop function call i can use, to set the t_libpd_printhook field in the DLL?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
thalm
  • 2,738
  • 2
  • 35
  • 49
  • ah, didn't know of that one, but how would i assign a delegate to it then? – thalm Apr 08 '12 at 21:43
  • yep, i accepted your answer now, as its the correct answer to my question. but as the dll i use is open source, i will probably add the setter methods as usr suggested. i found this to be helpful: http://stackoverflow.com/questions/2167895/howto-implement-callback-interface-from-unmanaged-dll-to-net-app – thalm Apr 08 '12 at 22:01
  • Interesting question and I do agree that a setter is the right solution if you are compiling the native code. – David Heffernan Apr 08 '12 at 22:06

2 Answers2

4

You can use LoadLibrary and GetProcAddress to obtain a pointer to the exported libpd_printhook variable. You can then use Marshal.WriteIntPtr and Marshal.GetFunctionPointerForDelegate to assign to the delegate.

[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);

[DllImport("kernel32.dll", SetLastError=true)]
static extern bool FreeLibrary(IntPtr hModule);

.....

IntPtr lib = LoadLibrary(@"mydll.dll");
IntPtr plibpd_printhook = GetProcAddress(lib, "libpd_printhook");
Marshal.WriteIntPtr(plibpd_printhook, 
    Marshal.GetFunctionPointerForDelegate(mydelegate));
FreeLibrary(lib);

You will want to add the error checking that I excised in the interests of a concise example.

Now, if you are in control of the unmanaged library I would still recommend adding a function to encapsulate writing to this function pointer. That feels like a better interface to me.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • thank you, very good example! i will evaluate both ways. as i have the sources of the dll i can write the setter methods, which is less work and the cleaner interface as you suggest. – thalm Apr 08 '12 at 21:59
3

PInvoke does not support exported variable. You need to create an unmanaged function which takes your delegate and copies it into the field.

usr
  • 168,620
  • 35
  • 240
  • 369