我正在尝试调用 C++ dll 中可用的方法
HRESULT WINAPI TestMethod(
_Out_ BOOL *isSuccess,
_In_opt_ DWORD UsernmaeLength,
_Out_opt_ LPWSTR userName );
我用 C# 编写的包装器方法如下所示
[DllImport("Test.dll", CharSet = CharSet.Unicode, SetLastError = true ,CallingConvention = CallingConvention.StdCall)]
public static extern int TestMethod (
IntPtr isSuccess,
[In, Optional] int UsernmaeLength,
out string userName
);
我在程序中调用这个方法
Wrapper. TestMethod (isSuccess, 200, out userName);
我收到 System.AccessViolationException
尝试用
更改 C# 包装器方法[DllImport("Test.dll", CharSet = CharSet.Unicode, SetLastError = true ,CallingConvention = CallingConvention.StdCall)]
public static extern int TestMethod (
bool isSuccess,
[In, Optional] int UsernmaeLength,
out string userName
);
//Caller
bool isSuccess = false;
Wrapper. TestMethod (isSuccess, 200, out userName);
你能帮我理解我在这里做错了什么吗?
最佳答案
_In_opt_ DWORD UsernmaeLength
SAL 注释不是很有用。它可能试图告诉您的是,您可以为字符串缓冲区参数传递 NULL。在这种情况下,您传递的缓冲区长度无关紧要。它实际上不是 [可选],如果您真的不想返回字符串,您可以考虑简单地传递 0。
第三个参数不能是 String 或 out,因为它是一个不可变类型,并且该函数想要写入您传递的缓冲区。它必须是 StringBuilder。第二个参数必须是它的容量。请务必使 StringBuilder 足够大以适合用户名。如果不是,那么会发生什么不是很明显,希望函数然后只返回错误代码而不是静默截断字符串。测试一下。
第一个参数是通过引用传递的 bool,[Out] out bool。它不太可能是 SetLastError,它只能由 winapi 函数完成。它已经返回了一个嵌入在 HResult 中的错误代码。小于 0 的值是一个错误。 Stdcall 是默认值。总结:
[DllImport("Test.dll", CharSet = CharSet.Unicode)]
public static extern int TestMethod (
[Out] out bool isSuccess,
int userNameLength,
StringBuilder userName
);
称为:
bool success;
var name = new StringBuilder(666);
int hr = TestMethod(out success, name.Capacity, name);
if (hr < 0) Marshal.ThrowExceptionForHR(hr);
如果您仍然遇到问题,那么如果您无法自行调试,则需要此代码作者的帮助。提供一个小的重现,这样他就可以轻松地重现问题。
关于c# - 从 C# 调用 C++ dll 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48922166/