我为c控制台应用程序创建了一个包装器,我在其中定义了一个结构,用于将输出传递给c #windows窗体。 struct包含一个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#Part:
[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来提取结构中包含的字符串。我尝试使用How can I convert an unmanaged IntPtr type to a c# string?中建议的编组操作,但我的结果只是一个数字。 有没有其他方法可以将IntPtr转换为c代码中使用的正确字符串?
edit:正确传递struct中的整数。问题只出现在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部分代码。
答案 0 :(得分:2)
要将IntPtr
转换为String
,请使用Marshal.PtrToStringAnsi
方法
struct_name s = compute_calc(...);
string str = Marshal.PtrToStringAnsi(s.s);
请注意,如果compute_calc
函数分配了内存,则可能还需要在托管代码中释放它。无法肯定,因为它取决于compute_calc
答案 1 :(得分:1)
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);
请注意,我还从结构声明中删除了Pack = 1
。除非C代码使用#pragma pack
,否则它不应该这样做,否则会导致64位代码不匹配。