2015-06-10 173 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()