0

我目前正在用 C# 开发 Excel 插件,并且正在使用与 C++ 库的互操作。两者都是我开发的。C++ 库不是一个 COM 组件,而只是一个导出一些函数的 DLL。

我有一个 C# 函数,我想将一个数字和两个字符串传递给 C++ 函数,然后 C++ 函数返回一个字符串。首先我尝试直接返回一个字符串,所以原型看起来像

//C#
[return: MarshalAs(UnmanagedType.LPStr)]
private static extern string Function([MarshalAs(UnmanagedType.I4)] int number,
                                      [MarshalAs(UnmanagedType.LPStr)]string str1,
                                      [MarshalAs(UnmanagedType.LPStr)] string str2);
//C++
extern "C" __declspec(dllexport) string Function(int, char*, char*);

(顺便说一句,我已经在 C# 中将此函数的调用约定设置为 Cdecl)

然后当我调用C#版本,进入C++(调试时),发现参数移位了,所以整数是指向第一个字符串的指针的值,第一个字符串是第二个字符串,第二个字符串指向其他地方。我也查了内存,发现参数没有按照_cdecl约定传递,整数是最后压入栈的(没问题),但是两个字符串的位置调换了。编译器添加了许多其他信息,因此我不想更深入地了解这一点。

但是,后来我把返回字符串改成了参数,原型看起来像

//C#
private static extern void Function([MarshalAs(UnmanagedType.I4)]int number,
                                    [MarshalAs(UnmanagedType.LPStr)] string str1,
                                    [MarshalAs(UnmanagedType.LPStr)] string str2,
                                    [MarshalAs(UnmanagedType.LPStr), Out] StringBuilder returnStr);
//C++
extern "C" __declspec(dllexport) void Function(int, char*, char*, string&);

现在参数已正确传递。

所以我的第一个问题是,这是怎么发生的?

我的第二个问题是,即使使用第二种方法,我也无法让程序正确运行,程序从C++函数返回时崩溃(实际上在C++函数中,唯一要做的就是调用一个类的另一个成员函数,所以这个函数就像是成员函数的一个包装器,而程序在返回成员函数的时候就崩溃了。由于warpper函数只是调用了成员函数,所以我不知道问题出在哪里)。

有谁知道如何做到这一点?所以这个函数的重点是取一个数字和两个字符串,然后返回另一个字符串。

先谢谢了。

4

1 回答 1

0

看这篇关于在非托管代码中使用stringbuilder的文章

尝试这样的事情:

//C#
public string Function(int number, string str1, string str2)
{
    StringBuilder sbStr1 = new StringBuilder(str1);
    StringBuilder sbStr2 = new StringBuilder(str2);
    StringBuilder sbReturnStr = new StringBuilder(1024);
    Function(number, sbStr1 , sbStr2 , sbReturnStr , sbReturnStr.Capacity);
    return sbReturnStr.ToString();
}

//C# p/invoke
private static extern void Function(int number, StringBuilder str1, StringBuilder str2, StringBuilder returnStrBuffer, int size);

//C++
extern "C" __declspec (dllexport) void __stdcall Function(int number, const char* str1, const char* str2, char* returnStrBuffer, int size)
{
     //fill the returnStrBuffer
     strncpy(returnStrBuffer, "blablalb", size); //example!!
}
于 2012-08-24T08:20:17.733 回答