访问库函数时,char **封送处理问题

时间:2019-06-10 10:59:41

标签: c# linux gcc mono

我要将用C ++ / VisualStudio写的现有库/ DLL移植到代码块/ GCC。 Windows中的DLL已在C#,C,C ++,Python,Delphi,Java,VB.NET,LabVIEW等中进行了测试,并且运行良好且稳定。 但是,将其移植到Linux时,在从Mono / C#对其进行测试时遇到了问题,而在FreePascal和Python上却无法正常工作。

问题的根源是一个函数,该函数检测参数的设备,并通过参数返回一个整数,该整数包含检测到的设备的数目以及设备所在的路径列表(字符的ASCII字符串的数组): / p>

int DetectDevices(char ** DevicePaths);

我将结果复制到库中的方式是:

i=0;
for (vector<string>::iterator it=lstDetected.begin(); it!=lstDetected.end(); ++it)
    strcpy(DevicePaths[i++], (*it).c_str());

在C#中,我使用以下代码声明外部函数:

[DllImport(LIBRARY_PATH)]
public static extern int DetectDevices([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] string[] DevicePaths);

我想指出的是,实际上我在调用函数并获取返回值之前在C#中保留了一些内存空间:

string[] DevicePaths = new string[50];
for (int i=0; i<DevicePaths.Length; i++)
    DevicePaths[i] = new string('\0', 255);

这在Windows / VisualStudio中工作正常,但在Linux / Mono中工作不正常。

用LPWStr替换LPStr并执行调试,表明字符已经到达,但对于LPStr中的所有字符,接收到的等效ASCII码为0,而在LPWStr中为63。

我认为这可能与字符编码有关,但是我可能错了。

有人对这里可能出什么问题有任何想法吗? 帮助将不胜感激!

2 个答案:

答案 0 :(得分:1)

我终于设法找到了封送处理问题的解决方案。

在Windows(.NET Framework)和Visual Studio中,允许通过以下方式返回字符串的C数组(char数组):

[DllImport(LIBRARY_PATH)]
public static extern int DetectDevices([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] string[] DevicePaths);

由于某种原因,这在Linux / Mono中不起作用,我不得不使用以下方法:

public static extern int DetectDevices(IntPtr[] pDevicePaths);

,然后在代码中使用以下方法检索每个字符串:

const int VCOUNT = 50;
const int MAXSTRINGSIZE = 255;
string[] MyValues = new string[VCOUNT];

IntPtr[] ptr = new IntPtr[VCOUNT];
for (int i = 0; i < ptr.Length; i++) ptr[i] = Marshal.AllocCoTaskMem(MAXSTRINGSIZE);

int n = DetectDevices(ptr);
if (n > 0) {
    for (int i = 0; i < n; i++) {
        StringBuilder sb = new StringBuilder(Marshal.PtrToStringAnsi(ptr[i]));
        MyValues[i] = sb.ToString();
    }
}

这是一种更具C / C ++风格的样式,它增加了复杂性但很有意义。 因此,我相信Mono尚未完全实现,或者某个地方存在错误。

如果有人有更好的解决方案,我将不胜感激。

答案 1 :(得分:0)

尝试使用<span class="checkmark"></span> ,它将字符串转换为平台的默认字符串编码。对于Mono,这是LPTStr

  • UTF-8 => ansi
  • UnmanagedType.LPStr => Unicode
  • UnmanagedType.LPWStr =>平台默认值

还有其他UnmanagedType.LPTStr可能也可以帮助您……UnmanagedType ...?

如果这样做没有帮助,请考虑使用“自定义封送处理”或“手动封送处理”。

documentation很好。