我已经搜索了stackoverflow这个问题,但没有找到这个问题。特别是,当C#端管理内存而不是相反时,我发现了很多关于检索C ++字符串引用(char **)的问题。
情况如下。我有一个DLL(在VC ++ 2012上编写),我自己写的。它从文件加载和解析数据,然后让任何使用DLL的人以多种方式访问这些数据(通过实际的直接内存访问,出于性能原因)。使用这个DLL的C ++中的任何程序显然都没有问题。似乎是C#......
一点背景:
DLL提供了接受char **(char *数组)参数的导出函数,其元素被设置为DLL中的内存位置,然后在调用后由DLL的用户进一步处理。
示例可能如下所示(示例实现):
int myFunction(char* dataArray[], int row)
{
for (int i= 0; i < _something; ++i)
{
dataArray[i] = _some_char_ptr
}
}
这就是被调用者在C ++中的实现方式:
char** data = new char*[__num_fields];
myFunction(data, __some_row);
for (int i= 0; i < __something; ++i)
{
cout << data[i] << endl;
}
特殊 - 因此与我发现的所有问题不同 - 关于这是被调用者在调用点之后分配一个char *列表到DLL本身分配的内存位置。
现在,我必须说,我只使用C#,因为你可以在notime中获得非常简单的GUI。我正在研究的C#GUI工具是用于加载DLL的完整性测试数据。我根本没有深刻的C#。到目前为止我所尝试的并没有成功,我知道由于C#没有任何指针概念,可能没有解决这个问题的方法。我在Java中使用JNA加载DLL时发现的类似问题导致我不再使用Java进行此类测试。
现在我尝试了一些C#的东西,包括。上下文:
public static class DLLTest
{
// delegate object for the function:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int MyFunction_Type(out string[] dataArray, int row);
public static MyFunction_Type MyFunction { get; private set; }
public static void Load()
{
IntPtr dllAddress = DllUtilities.LoadLibrary(@"__dll_path");
IntPtr procAddress = DllUtilities.GetProcAddress(dllAddress, "myFunction");
MyFunction = (MyFunction_Type)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(MyFunction_Type));
}
}
然后我就这样调用这个函数:
string[] data = new string[__num_fields];
DLLTest.MyFunction(out data, __row)
使用像普通字符串,整数,布尔值这样的东西就像魅力一样的代码。只是这些字符串数组一直在困扰我: - )
注意:我无法改变DLL的工作方式,因为我为老板写了这个,并且他在C ++和Delphi程序中都使用它很好。它运行良好,我们不会改变DLL本身的任何内容,因为它确实很好。
非常感谢任何帮助或澄清,非常感谢,问候
答案 0 :(得分:1)
out string[] dataArray
是char**
参数的错误翻译。它应该是:
IntPtr[] dataArray
调用C#代码然后在调用函数之前分配数组。就像C ++代码一样。
IntPtr[] data = new IntPtr[__num_fields];
int retval = DLLTest.MyFunction(data, __row);
然后,您可以使用Marshal
类访问内存到您的内容,以读取IntPtr
指针后面的非托管内存。
调用约定看起来有点奇怪。如上所述,C ++函数是cdecl
。正如汉斯所说,还必须有一些机制让DLL知道传入的数组有多长。