2012-04-08 67 views
4

我正在爲非託管C dll寫C#綁定。設置來自C的非託管C dll的公共字段#

DLL提供5個鉤子返回幾個數據:

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

和出口的字段,如:

EXTERN t_libpd_printhook libpd_printhook; 

現在我使用Interop Assistant生成綁定代碼,這給了我只是一個代表定義:

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

那麼有沒有一些神奇的Interop函數調用我可以使用,在DLL中設置t_libpd_printhook字段?

+0

啊,不知道那個,但是我怎麼會指定一個代表呢? – thalm 2012-04-08 21:43:04

+0

是的,我現在接受你的答案,因爲它是我的問題的正確答案。但由於我使用的DLL是開源的,我可能會像usr建議的那樣添加setter方法。我發現這是有幫助的:http://stackoverflow.com/questions/2167895/howto-implement-callback-interface-from-unmanaged-dll-to-net-app – thalm 2012-04-08 22:01:20

+0

有趣的問題,我同意,一個二傳手是如果您正在編譯本機代碼,那麼這是一個正確的解決方案 – 2012-04-08 22:06:10

回答

4

您可以使用LoadLibraryGetProcAddress獲取指向導出的libpd_printhook變量的指針。然後您可以使用Marshal.WriteIntPtrMarshal.GetFunctionPointerForDelegate分配給代理人。

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

您將要添加的錯誤檢查,我在一個簡潔的例子的利益切除。

現在,如果你在控制非託管庫,我仍然會建議添加一個函數來封裝寫入這個函數指針。這對我來說就像一個更好的界面。

+0

謝謝,非常好的例子!我會評估這兩種方式。因爲我有DLL的來源,我可以編寫setter方法,這是更少的工作和更清潔的接口,如你所建議的。 – thalm 2012-04-08 21:59:06

3

PInvoke不支持導出的變量。您需要創建一個非託管函數,它將您的委託並將其複製到該字段中。

+1

是的,絕對你是真的 – pylover 2012-04-08 21:16:49

+1

好吧,所以我必須在C中添加設置方法...謝謝! – thalm 2012-04-08 21:20:04