2008-10-01 62 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