2008-10-01 63 views
7

我有一个函数中定义为本地DLL如下:元帅C++“串”级/调用

#include <string> 
void SetPath(string path); 

我试图把这个微软的P/Invoke互操作助理,但它扼流圈“字符串”类(我认为这是从MFC?)。我试图封送它作为各种不同类型(C#字符串,字符[],字节[]),但每次我得到一个NotSupportedException或本机程序集异常(取决于我试着编组)。

像以前做过的任何本机/托管Interop使用本地字符串类的地方?有没有办法对此进行统一?我会不得不写我自己的Marshaller?

+0

大的问题;我很惊讶它不能自动工作。 http://msdn.microsoft.com/en-us/library/1b4az623.aspx – 2008-10-01 17:36:15

+0

我也很惊讶......没有什么主要原因,它不应该......但似乎STL不会与它合作... 另外...我只是改变功能使用WCHAR,但它不是我可以改变的DLL。 – 2008-10-01 17:48:50

回答

6

看起来你正在尝试使用C++标准库字符串类。我怀疑这对元帅来说很容易。更好地坚持char *和Marshal作为StringBuilder。这就是我通常所做的。你将不得不添加一个为你生成C++字符串的包装器。

2

PInvoke互操作助手只支持C而不是C++。不幸的是,MFC字符串类(CString我相信?)是C++,不能通过助手工作。请尝试使用以下内容

void SetPath(__in const WCHAR* path); 
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); 
    } 
} 

对于一些细节,请参见下面的链接,

C#/.NET PInvoke Interop SDK

(我的SDK工具的作者)

一旦你有你的C C#的包装类++类准备好了,它很容易实现ICustomMarshaler,这样你就可以编组来自.NET的C++对象。

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.icustommarshaler.aspx