0

为原生 (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);

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

4

2 回答 2

1

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

于 2013-10-13T14:49:30.113 回答
0

我怀疑您的本机库没有使用 __cdecl 调用约定,而是使用 __stdcall 之类的东西。一般来说,最好不要冒险并在本机库级别强制执行调用约定,而不是让编译器或项目选项来确定它。尝试这个:

[DllImport("path\\to.dll", CallingConvention=CallingConvention.StdCall)]
于 2013-10-13T12:02:27.297 回答