Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 访问库函数时char**的封送处理问题_C#_Linux_Gcc_Mono - Fatal编程技术网

C# 访问库函数时char**的封送处理问题

C# 访问库函数时char**的封送处理问题,c#,linux,gcc,mono,C#,Linux,Gcc,Mono,我正在将一个用C++/VisualStudio编写的现有库/DLL移植到codeblocks/GCC。Windows中的DLL已经在C、C、C++、Python、Delphi、java、VB.NET、LabVIEW等测试,工作稳定、稳定。 然而,当将它移植到Linux时,我在从Mono/C#测试它时遇到了问题,而在FreePascal和Python中它工作正常 问题的根源是一个函数,该函数检测某些设备,并通过参数返回一个整数,其中包含检测到的设备数量,以及设备所在的路径列表(ASCII字符字符串

我正在将一个用C++/VisualStudio编写的现有库/DLL移植到codeblocks/GCC。Windows中的DLL已经在C、C、C++、Python、Delphi、java、VB.NET、LabVIEW等测试,工作稳定、稳定。 然而,当将它移植到Linux时,我在从Mono/C#测试它时遇到了问题,而在FreePascal和Python中它工作正常

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

int DetectDevices(char ** DevicePaths);
我在库中复制结果的方式是:

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

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

string[] DevicePaths = new string[50];
for (int i=0; i<DevicePaths.Length; i++)
    DevicePaths[i] = new string('\0', 255);
string[]设备路径=新字符串[50];

对于(int i=0;i尝试使用
LPTStr
,它将字符串转换为平台的默认字符串编码。对于Mono,这是
UTF-8

  • UnmanagedType.LPStr
    =>ansi
  • UnmanagedType.LPWStr
    =>unicode
  • UnmanagedType.LPTStr
    =>平台默认值
还有其他
UnmanagedType
也可以帮助…
BStr
也许

如果这没有帮助,那么考虑使用自定义封送处理或手动封送处理。< /P>


这个问题非常好。

我终于找到了封送问题的解决方案

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

[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();
    }
}
然后,在代码中,使用以下方法检索每个字符串:

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();
    }
}
const int VCOUNT=50;
常量int MAXSTRINGSIZE=255;
字符串[]MyValues=新字符串[VCOUNT];
IntPtr[]ptr=新的IntPtr[VCOUNT];
对于(int i=0;i0){
对于(int i=0;i
这是一种更为C/C++的风格,它增加了复杂性,但也有意义。 所以我认为要么Mono没有完全实现,要么某处有一个bug


如果有人有更好的解决方案,我会非常感激。

编译时使用的字符集是什么(unicode还是多字节)?
strcpy(DevicePaths[I++],(*it).c_str())
如果你没有超过数组,你在哪里检查呢?@LeonardoSeccia真诚地说,我没有在codeblocks/GCC中设置这个,所以我认为它被视为ASCII@Selvin因为我是测试这个的人,我可以确认内存不是问题。我不认为这是相关的。还要考虑到我已经简化了这个问题在这里,删除所有不相关的代码。可能是GCC上的字符编码问题?我应该如何正确设置字符编码?我已经测试了上面的所有选项,但没有成功。LPWStr返回正确的字符计数,但所有字符值都是63。BStr创建了一个异常。我也检查了此文档,但没有找到任何异常这对我的特殊问题很有用。@Carles-关于
LPTStr
?你得到了什么?什么都没有,都设置为初始值:0。唯一给我带来问题的是LPWStr,它的结果是我期望的字符数,但它们都设置为63(我认为是多字节或unicode字符的较高部分)。