调用本机函数时,最后一个参数似乎已损坏

本文关键字:参数 已损坏 最后一个 本机 函数 调用 | 更新日期: 2023-09-27 18:35:13

正在为本机 (C) 库处理 C# 包装器。我在本机库中有以下函数原型:

typedef struct _NativeObj *       NativeObj;
typedef struct AnotherNativeObj * AnotherNative;
__declspec(dllimport) NativeObj createNativeObj (
    AnotherNative * anotherNative,
    FirstCallback   firstCallback,
    void *          firstOpaque,
    SecondCallback  secondCallback,
    void *          secondOpaque,
    ThirdCallback   thirdCallback,
    void *          thirdOpaque,
    const char *    firstString,
    const char *    secondString,
    const char *    thirdString,
    time_t          timeout,
    char *          fourthString,
    int             firstInt,
    int             secondInt,
    int             thirdInt,
    int             fourthInt,
    char *          fifthString,
    int             fifthInt,
    char *          sixthString);

这是 C# 代码中的声明:

public delegate int ThirdCallbackDelegate(...);
public const uint NO_TIMEOUT = 0;
private uint   timeout   = NO_TIMEOUT;
private string fourthString;
private uint   firstInt  = 0;
private bool   secondInt = false;
private bool   thirdInt  = true;
private bool   fourthInt = true;
private string fifthString;
private bool   fifthInt  = false;
public string  sixthString { get; set; }
[DllImport("path''to.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern IntPtr createNativeObj(
    IntPtr                 anotherNative,
    FirstCallbackDelegate  firstCallback,
    IntPtr                 firstOpaque,
    SecondCallbackDelegate secondCallback,
    IntPtr                 secondOpaque,
    ThirdCallbackDelegate  thirdCallback,
    IntPtr                 thirdOpaque,
    string                 firstString,
    string                 secondString,
    string                 thirdString,
    int                    timeout,
    string                 fourthString,
    int                    firstInt,
    int                    secondInt,
    int                    thirdInt,
    int                    fourthInt,
    string                 fifthString,
    int                    fifthInt,
    string                 sixthString);

以及参数背后的逻辑:

IntPtr myOpaque = createNativeObj(IntPtr.Zero,
            null,
            IntPtr.Zero,
            null,
            IntPtr.Zero,
            thirdCallbackDelegate,
            IntPtr.Zero,
            firstString,
            secondString,
            thirdString,
            (int)timeout,
            fourthString,
            (int)firstInt,
            Convert.ToInt32(secondInt),
            Convert.ToInt32(thirdInt),
            Convert.ToInt32(fourthInt),
            fifthString,
            Convert.ToInt32(fifthInt),
            sixthString);

在运行时,就在本机函数开始时,超时后参数的值已损坏。

调用本机函数时,最后一个参数似乎已损坏

在 Windows 上,使用 MS 工具,假设您没有定义_USE_32BIT_TIME_Ttime_t类型为 8 字节宽。这意味着您需要在 C# p/invoke 代码中将其声明为 long 以匹配。

我怀疑您的本机库没有使用__cdecl调用约定,而是使用类似__stdcall的约定。通常,最好不要冒险并在本机库级别强制实施调用约定,而不是让编译器或项目选项确定它。试试这个:

[DllImport("path''to.dll", CallingConvention=CallingConvention.StdCall)]