从c char *转换为string / IntPtr c#

时间:2014-03-18 15:09:32

标签: c# c pinvoke

我为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部分代码。

2 个答案:

答案 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位代码不匹配。