我试图调用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);
我正在获得系统。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。
第三个参数不能是字符串或外出,因为这是不变的类型,并且该功能希望写入您通过的缓冲区。它必须是弦乐器。第二个论点必须是其能力。确保使StringBuilder足够大以适合用户名。如果不是这样,那就不是很明显了,希望该功能只需返回错误代码,而不是默默地截断字符串。测试。
第一个参数是通过引用[OUT] BOOL传递的BOOL。它不太可能仅由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);
如果您仍然遇到麻烦,则如果您无法自己调试,则需要该代码的作者的帮助。有一个少量的repro可用,以便他可以轻松地复制问题。