我正在尝试调用C ++ dll中可用的方法
function toolsQueryResult() {
const query = `query{......}`
return request('http://...', query, ).then(data => {
return data
})
}
// just to emulate your api call
function request(foo) {
return Promise.resolve(["item1", "item2"]);
}
var toolsQueryResult = toolsQueryResult();
var toolsNames = [];
toolsQueryResult.then(function(result) {
result.forEach(function(item) {
toolsNames.push(item)
})
console.log("am executed after you waited for promise to complete - in this case successfully, so you can see the tool sets")
console.log(toolsNames)
})
console.log("am executed before you could resolve promise")
console.log(toolsNames)
Wrapper方法我用C#编写的方法就像这样
HRESULT WINAPI TestMethod(
_Out_ BOOL *isSuccess,
_In_opt_ DWORD UsernmaeLength,
_Out_opt_ LPWSTR userName );
我在程序中调用此方法
[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
);
我收到System.AccessViolationException
尝试使用
更改C#包装器方法Wrapper. TestMethod (isSuccess, 200, out userName);
请你帮我理解我在这里做错了什么?
答案 0 :(得分:3)
_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);
如果您仍然遇到问题,那么如果您无法自行调试,则需要此代码作者的帮助。有一个小的repro可用,所以他可以轻松地重复这个问题。