从C#调用C ++ DLL方法

时间:2018-02-22 07:53:23

标签: c# c++

我正在尝试调用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);

请你帮我理解我在这里做错了什么?

1 个答案:

答案 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可用,所以他可以轻松地重复这个问题。