2015-06-10 142 views
2

我在C++下面的功能,我想從C#調用:如何在C++中調用返回C#字符串的函數?

std::string getString(); 

我最好如何做到這一點(使用的PInvoke)?

我正確地認爲從C++到C#的返回分配內存有問題,而且在C#中分配一個大字符串然後將它傳遞給C++進行寫入會更好(更容易)?

在這種情況下,我想我應該換C++函數與C:?

extern "C" 
{ 
    __declspec(dllexport) void get_string(int size, char *buffer) 
    { 
     call getString and strncpy to buffer 
    } 
} 
+0

我認爲返回'std: :string' - 除非您使用manage C++,否則C#CLR只能處理基元。我會選擇後者(將'char *'傳遞給C++實現) – NirMH

+1

正如你寫的那樣...只要記住'strncpy'不能保證添加終止'\ 0',所以你應該手動添加它。 – xanatos

+0

@xanatos:非常感謝您的幫助!我該如何在C#中聲明緩衝區?字節[]還是我使用StringBuilder? – Andy

回答

4

的傳統方式來做到這一點是:

__declspec(dllexport) void get_string(int size, char *buffer) 
{ 
    std::string str = getString(); 
    strncpy(buffer, str.c_str(), size); 
    buffer[size - 1] = '\0'; 
} 

C#的一面:

[DllImport("NativeLibrary", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] 
public static extern void get_string(int len, [Out] StringBuilder sb); 

,然後(很重要!你必須預先尺寸StringBuilder

var sb = new StringBuilder(100); 
get_string(sb.Capacity, sb); 
string str = sb.ToString(); 

可以使用char[],但它更復雜,因爲那時你必須手動「修剪」\0

還有一種更復雜的方式與內存少了一個副本,做...但它更是一個有點複雜:

C++方面:

__declspec(dllexport) void get_string(void (*func)(const char*)) 
{ 
    std::string str = getString(); 
    func(str.c_str()); 
} 

C#的一面:

[DllImport("NativeLibrary", CallingConvention = CallingConvention.Cdecl)] 
public static extern void get_string(StringFromIntPtr.FromIntPtrDelegate func); 

public class StringFromIntPtr 
{ 
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
    public delegate void FromIntPtrDelegate(IntPtr ptr); 

    public string Value { get; protected set; } 

    public void FromIntPtr(IntPtr ptr) 
    { 
     Value = Marshal.PtrToStringAnsi(ptr); 
    } 
} 

然後你使用這樣的:

var sfip = new StringFromIntPtr(); 
get_string(sfip.FromIntPtr); 
string str = sfip.Value; 

關鍵是你將一個代理傳遞給C#方法,知道如何處理一個字符串的原始指針(例如通過使用Marshal.PtrToStringAnsi),並且C++代碼使用它。請注意,在C++/CLI中執行此操作會更容易(因爲您不需要委託,C++/CLI可以同時使用std::stringSystem.String^

3

如果您正在使用C++/CLI,您可以返回系統::字符串了。您可以構建從的getString()系統:: string的c_str()