2012-08-09 135 views
5

我在編組時遇到了一些問題,我自己也弄不清楚。我已經搜索了這個主題,但還沒有任何運氣,所以基本上我試圖從託管的C#應用​​程序調用非託管C函數。 C函數的簽名如下所示:如何使用WCHAR * out參數從C#調用C函數?

long MyFunction(WCHAR* upn, long upnSize, WCHAR* guid, long* guidSize); 

我不訪問該.dll文件,我只知道函數被曝光的使用,我知道什麼功能是應該做的,但我不知道里面發生了什麼,所以函數收到一個持有UserPricipalName的WCHAR * upn和一個提供UPN長度的long。同時傳遞WCHAR指針,函數寫回與通過的UPN關聯的對應GUID。 guidSize指針提供指針的大小,如果它太小,寫入的GUID沒有完全寫入。如果一切順利的函數應返回0(它從來沒有發生過,從C#調用時)

現在我的努力來調用和調用這個函數是這樣的:

[DllImport(@"MyDll.dll", EntryPoint = "MyFunction", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 
public static extern long MyFunction(IntPtr upnPtr, long upnSize, [Out, MarshalAsAttribute(UnmanagedType.LPWStr) ] StringBuilder guidPtr, IntPtr guidSizePtr); 


//my attempt to call the Dll's exposed function 
string upn = [email protected]; 
long upnSize = upn.Length; 
IntPtr upnPtr = Marshal.StringToHGlobalUni(upn); 

IntPtr guidSizePtr = Marshal.AllocHGlobal(sizeof(long)); 
Marshal.WriteInt32(GuidSizePtr, 128); 
var guidSB = new StringBuilder(128); 

result = MyFunction(upnPtr, upnSize, guidSB, guidSizePtr); 

我收到的結果AccessViolationException。我玩過很多變種來調用這個函數,但我從來沒有設法得到0作爲返回值,我從來沒有能夠讀出我想要做的GUID。

任何幫助,這將不勝感激。

+0

在P/Invoke函數聲明中可能最容易使用'StringBuilder'。 – 2012-08-09 08:12:32

+0

@CodyGray它已經是一個'StringBuilder guidPtr'。 'guidPtr'是輸出參數,'upn'是輸入。 – hvd 2012-08-09 08:13:07

回答

8

聲明功能:

[DllImport(@"MyDll.dll", EntryPoint = "MyFunction", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 
    public static extern int MyFunction([MarshalAsAttribute(UnmanagedType.LPWStr)] string upnPtr, int upnSize, [MarshalAsAttribute(UnmanagedType.LPWStr)] StringBuilder guidPtr, ref int guidSizePtr); 

調用它,如下所示:

 string upn = "[email protected]"; 
     var guidSB = new StringBuilder(128); 
     int guidSizePtr =guidSB.Capacity; 
     MyFunction(upn, upn.Length, guidSB, ref guidSizePtr); 

注意,長期在C++是32位的,所以你應該定義所有這些情況下爲INT您C#代碼。

+0

非常感謝你的魅力! :d – butterwaach 2012-08-09 09:07:00