从c char*到string/IntPtr的转换
本文关键字:IntPtr 转换 string char | 更新日期: 2023-09-27 17:50:51
我为c控制台应用程序创建了一个包装器,其中定义了一个结构体来将输出传递给c# windows窗体。结构体包含一个char*变量,必须在c#代码中正确解释。我使用了IntPtr类型,但我没有获得想要的结果,只有一个数字,我认为是可能的内存地址。
C部分:struct struct_name{
int a;
char* s;
}
extern __declspec(dllexport) struct_name compute_calc(int opt, char* file_1, char* file_2)
c#部分:[DllImport("dll_name.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern struct_name compute_calc(int opt, String file1, String file2)
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Auto)]
public struct struct_name{
Int32 a;
IntPtr s;
}
在应用程序中,我用以下代码调用函数
struct_name result = levenshtein(1, filePath1, filePath2);
在这一点上,我的问题是使用char*/IntPtr来提取结构体中包含的字符串。我尝试使用编组操作,建议在如何将非托管IntPtr类型转换为c#字符串?但我的结果只是一个数字。是否有其他方法将IntPtr转换为c代码中使用的正确字符串?
edit:结构体中的整数被正确传递。问题只存在于char*
edit2:
struct_name result;
{..some code...}--> output int N, char* s0
result.s = (char*)malloc( sizeof(char)*n);
result.a=N;
result.s=_strdup(s0)
return result;
这是一个建议中要求的C部分代码
Marshal.PtrToStringAnsi()
是您需要将IntPtr
转换为字符串的内容。IntPtr
装着char*
, Marshal.PtrToStringAnsi()
就是你要找的人。
然而,你已经试过了,没有成功。所以我怀疑你的问题更根本。也许在互操作边界的两边处理大型结构体的方式上存在二进制不匹配。这是互操作的一部分,不同的工具表现不同。结构体应该总是使用out
参数返回。将本机代码更改为如下所示:
__declspec(dllexport) int compute_calc(int opt, const char* file_1,
const char* file_2, struct_name* result)
被管理方为:
[StructLayout(LayoutKind.Sequential)]
public struct struct_name{
int a;
IntPtr s;
}
[DllImport("dll_name.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int compute_calc(int opt, string file1, string file2,
out struct_name result);
注意,我还从struct声明中删除了Pack = 1
。除非C代码使用#pragma pack
,否则这将导致64位代码下的不匹配。
使用Marshal.PtrToStringAnsi
方法将IntPtr
转换为String
struct_name s = compute_calc(...);
string str = Marshal.PtrToStringAnsi(s.s);
注意,如果compute_calc
函数分配了内存,它可能也需要在托管代码中释放。不能肯定,因为这取决于compute_calc