调用本机函数时,最后一个参数似乎已损坏
本文关键字:参数 已损坏 最后一个 本机 函数 调用 | 更新日期: 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_T
,time_t
类型为 8 字节宽。这意味着您需要在 C# p/invoke 代码中将其声明为 long
以匹配。
我怀疑您的本机库没有使用__cdecl调用约定,而是使用类似__stdcall的约定。通常,最好不要冒险并在本机库级别强制实施调用约定,而不是让编译器或项目选项确定它。试试这个:
[DllImport("path''to.dll", CallingConvention=CallingConvention.StdCall)]