2012-08-09 133 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