C到C#互操作:如何处理此方法

C到C#互操作:如何处理此方法,c#,interop,C#,Interop,C声明: struct t_name { char first_name[128]; char nickname[128]; int32_t words[7]; uint16_t parts_of_speech[7]; uint32_t language; bool has_name; }; char* Translation_TranslateNameEnglish(DFHackObject* trans, const t_name* name

C声明:

struct t_name
{
    char first_name[128];
    char nickname[128];
    int32_t words[7];
    uint16_t parts_of_speech[7];
    uint32_t language;
    bool has_name;
};

char* Translation_TranslateNameEnglish(DFHackObject* trans, const t_name* name);
我在C#中的表现:

电话:

DFHack.Translation_TranslateNameEnglish(translation, ref name)
使用IntPtr作为第一个参数并没有问题,我在类似的调用中也有类似的功能。DFName结构在另一个调用中填充,它包含有效数据。 然而,不起作用的是对翻译英语的呼唤。当该行执行时,我得到一个错误“试图读取或写入受保护的内存。这通常表示其他内存已损坏。” 我做错了什么

我忘了提到的一点可能很重要:DFName结构作为另一个结构的一部分进行检索

[StructLayout(LayoutKind.Sequential), Serializable]
public struct DFCreature
{
// Snip
    public DFName Name;
// Snip
}
使用方法检索

public static extern int Creatures_ReadCreature(IntPtr ptr, uint index, out DFCreature creature);

绝对确保“C”代码中的
sizeof(t#u name)
与C代码中的
Marshal.sizeof(typeof(DFName))
相同。如果不一样,您需要找出原因——特别是看看C代码中的打包选项,以及p/invoke签名中的Ansi/Unicode选项

更新:事实上,在这里检查,只要MS'C'编译器使用默认打包选项运行,它看起来就可以了,但如果发生更改,它绝对值得在您的环境中检查。

是,“尝试读取或写入受保护的内存。这通常表示其他内存已损坏。”这是预期的结果。这是因为您试图从函数中返回字符串值。在本例中,.NET framework创建字符串对象并尝试释放内存,在内存中,您使用CoTaskMemFree函数从函数中获取字符串。据我所知,您没有使用CoTaskMemAlloc分配此内存,因此您的验证是正确的。为了避免这种情况,您应该将C#函数原型更改为返回IntPtr:

[DllImport(DllName)]
public static extern IntPtr Translation_TranslateNameEnglish(IntPtr ptr, ref DFName name);
您可以按如下方式进行操作:

string result = Marshal.PtrToStringAnsi(DFHack.Translation_TranslateNameEnglish(translation, ref name);
[编辑]

它也可能对您有用-

请使用相同的电子邮件/OpenID登录,这样您将作为同一个人被线程化,并且您将能够编辑您的答案,等等。不幸的是,使用您的方法和文章中描述的方法,我得到了相同的结果exception@Patrick:嗯,您有哪种类型的
name
?尝试使用StringBuilder来实现它。如果这不起作用,我现在没有更多的假设
string result = Marshal.PtrToStringAnsi(DFHack.Translation_TranslateNameEnglish(translation, ref name);