C to C#interop:如何处理此方法

时间:2011-04-22 08:54:13

标签: 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#中的表现如何:

[StructLayout(LayoutKind.Sequential), Serializable]
public struct DFName
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string FirstName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    public string NickName;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)]
    public int[] Words;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)]
    public ushort[] PartsOfSpeech;
    public uint Language;
    public bool HasName;
}

[DllImport(DllName)]
public static extern string Translation_TranslateNameEnglish(IntPtr ptr, ref DFName name);

电话:

DFHack.Translation_TranslateNameEnglish(translation, ref name)

使用IntPtr作为第一个参数是没有问题的,我有类似的调用。 DFName结构填充在另一个调用中,它包含有效数据。 然而,什么是无效的是对TranslateNameEnglish的调用。当该行执行时,我得到一个错误“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。” 我做错了什么?

我忘了提到哪些可能很重要: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);

2 个答案:

答案 0 :(得分:0)

确保“C”代码中的sizeof(t_name)与C#代码中的Marshal.SizeOf(typeof(DFName))相同。如果它不相同,你需要找出原因 - 特别是看看C代码中的打包选项,以及p / invoke签名中的Ansi / Unicode选项。

更新:实际上,在这里检查一下,看起来没问题,只要MS'C'编译器使用默认的打包选项运行,但是如果已经更改了,那么绝对值得检查你的环境。

答案 1 :(得分:0)

是,“尝试读取或写入受保护的内存。这通常表示其他内存已损坏。”是预期的结果。发生这种情况是因为您尝试从函数内返回字符串值。在这种情况下,.NET框架创建字符串对象并尝试释放内存,其中您使用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);

<强> [编辑]
它也可能对您有用 - Marshaling unmanaged char** to managed string[]