我在本机DLL中有一个函数,定义如下:
#include <string>
void SetPath(string path);
我试着将它放在微软的P / Invoke Interop助手中,但它在“字符串”类(我认为是来自MFC?)上窒息。
我尝试将它编组为各种不同的类型(C#String,char [],byte []),但每次我得到NotSupportedException或Native Assembly Exception(取决于我尝试过的编组)。
有没有人使用本机字符串类的Native / Managed Interop?有没有办法让这个元帅?我是否必须自己编写Marshaler?
答案 0 :(得分:6)
看起来您正在尝试使用C ++标准库字符串类。我怀疑元帅会很容易。最好坚持使用char *和Marshal作为StringBuilder。这就是我通常做的事情。您必须添加一个为您生成C ++字符串的包装器。
答案 1 :(得分:2)
PInvoke互操作助手仅支持C而不是C ++。不幸的是,MFC String类(CString我相信?)是C ++,不会通过助手工作。而是尝试使用以下
void SetPath(__in const WCHAR* path);
答案 2 :(得分:0)
是。您可以。实际上,不仅std::string
,std::wstring
,任何标准C ++类或您自己的类都可以被编组或实例化,并从C#/ .NET调用。
从.NET世界实例化C ++对象的基本思想是从.NET分配C ++对象的确切大小,然后调用从C ++ DLL导出的构造函数来初始化对象,然后您就可以调用任何函数来访问该C ++对象,如果任何方法涉及其他C ++类,您也需要将它们包装在C#类中,对于具有基本类型的方法,您可以简单地P / Invoke它们。如果你只有几种方法可以调用,那很简单,手动编码不会花费很长时间。完成C ++对象后,可以调用C ++对象的析构函数方法,该方法也是导出函数。如果它没有,那么你只需要从.NET中释放你的记忆。
这是一个例子。
public class SampleClass : IDisposable
{
[DllImport("YourDll.dll", EntryPoint="ConstructorOfYourClass", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void SampleClassConstructor(IntPtr thisObject);
[DllImport("YourDll.dll", EntryPoint="DoSomething", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void DoSomething(IntPtr thisObject);
[DllImport("YourDll.dll", EntryPoint="DoSomethingElse", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void DoSomething(IntPtr thisObject, int x);
IntPtr ptr;
public SampleClass(int sizeOfYourCppClass)
{
this.ptr = Marshal.AllocHGlobal(sizeOfYourCppClass);
SampleClassConstructor(this.ptr);
}
public void DoSomething()
{
DoSomething(this.ptr);
}
public void DoSomethingElse(int x)
{
DoSomethingElse(this.ptr, x);
}
public void Dispose()
{
Marshal.FreeHGlobal(this.ptr);
}
}
有关详细信息,请参阅以下链接
(我是SDK工具的作者)
一旦准备好了C ++类的C#包装类,就可以很容易地实现ICustomMarshaler
,这样就可以从.NET编组C ++对象了。
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.icustommarshaler.aspx