简体   繁体   English

从C#调用C ++ DLL方法

[英]Calling C++ dll Method from C#

I am trying to call method available in C++ dll 我试图调用C ++ DLL中可用的方法

HRESULT WINAPI TestMethod(
_Out_     BOOL   *isSuccess,
_In_opt_  DWORD  UsernmaeLength,
_Out_opt_ LPWSTR userName );

Wrapper method Which I have written in C# looks like this 我用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
    );

I am calling this method in program 我在程序中调用这个方法

Wrapper. TestMethod (isSuccess, 200, out userName);

I am getting System.AccessViolationException 我收到System.AccessViolationException

tried changing the C# wrapper method with 尝试用C改变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);

Could you please help me to understand what I am doing wrong here? 你能帮我理解我在这里做错了什么吗?

 _In_opt_  DWORD  UsernmaeLength

The SAL annotation is not very useful. SAL注释不是很有用。 What it probably is trying to tell you is that you can pass NULL for the string buffer argument. 它可能试图告诉你的是你可以为字符串缓冲区参数传递NULL。 In which case what you pass for the buffer length doesn't matter. 在这种情况下,为缓冲区长度传递的内容无关紧要。 It is not actually [Optional], you'd consider simply passing 0 if you really don't want a string back. 它实际上不是[可选],如果你真的不想要字符串,你可以考虑简单地传递0。

The 3rd argument cannot be String or out since that is an immutable type and the function wants to write into the buffer you pass. 第三个参数不能是String或out,因为它是一个不可变类型,函数想要写入你传递的缓冲区。 It must be StringBuilder. 它必须是StringBuilder。 The 2nd argument must be its Capacity. 第二个参数必须是它的容量。 Be sure to make the StringBuilder big enough to fit a user name. 一定要使StringBuilder足够大以适合用户名。 If it is not then it isn't very obvious what will happen, hopefully the function then just returns an error code instead of silently truncating string. 如果不是那么它会发生什么不是很明显,希望函数然后只返回错误代码而不是静默截断字符串。 Test that. 测试一下。

The 1st argument is bool passed by reference, [Out] out bool. 第一个参数是通过引用传递的bool,[Out] out bool。 Not very likely that it SetLastError, that is only done by winapi functions. 它不太可能是SetLastError,这只是由winapi函数完成的。 It already returns an error code embedded in the HResult. 它已经返回了HResult中嵌入的错误代码。 A value less than 0 is an error. 小于0的值是错误。 Stdcall is the default. Stdcall是默认值。 Summarizing: 总结:

[DllImport("Test.dll", CharSet = CharSet.Unicode)]
public static extern int TestMethod (
    [Out] out bool isSuccess,
    int userNameLength,
    StringBuilder userName
);

Called as: 被称为:

bool success;
var name = new StringBuilder(666);
int hr = TestMethod(out success, name.Capacity, name);
if (hr < 0) Marshal.ThrowExceptionForHR(hr);

If you still have trouble then you need the help of the author of this code if you cannot debug it yourself. 如果您仍然遇到问题,那么如果您无法自行调试,则需要此代码作者的帮助。 Have a small repro available so he can easily repro the issue. 有一个小的repro可用,所以他可以轻松地重现问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM