繁体   English   中英

将此DLL包含从VB.net转换为C#

[英]Translate this DLL include from VB.net to C#

这已经被要求了一百万次,但我仍然无法使它正常工作。 所以我问:我有一个DLL导入(非托管C / C ++代码),我想从C#调用它而无法正常工作。 我是从VB.net移植的,代码(有效)如下:

Module Module1
    Public Declare Function autodetect_SearchAxis Lib "autodetect.dll" (ByVal onusb As Boolean, ByVal searchsubadress As Byte, ByRef portname As String, ByRef devicelocation As String) As Integer
    Public AxisCom As String
    Public AxisAdress As Byte = 1
    Public Dummy As String
    Public rc As Integer
    Sub Main()
        Dummy = Space(1024)
        AXISCom = Space(1024)
        rc = autodetect_SearchAxis(False, AxisAdress, Dummy, AxisCom)
        Debug.WriteLine("rc: " + rc.ToString())
        Debug.WriteLine("AxisCom: " + AxisCom.ToString())
    End Sub
End Module

我没有手边的ATM尝试C#代码,但是我已经使用SttingBuilder类尝试了各种版本。 如果有人可以帮助我将此代码移植到C#,我将非常感激。 提前致谢!

编辑:

我现在有了DLL功能的签名:

int _stdcall autodetect_SearchAxis(bool onusb, BYTE searchsubadress, char* &portname, char* &devicelocation)

David Heffernan建议的解决方案部分起作用。 它正在工作(我没有错误消息),但是返回的字符串是垃圾。 本质上,这就是我已经在工作的内容(具有相同的垃圾输出)。 我不确定这是否与字符编码有关(我没有收到任何错误消息)。 希望签名有帮助。

基本上应该是:

using System.Diagnostics;
using System.Runtime.InteropServices;

public static class Module1
{
    [DllImport("autodetect.dll")]
    public static extern int autodetect_SearchAxis(bool onusb, byte searchsubadress, ref string portname, ref string devicelocation);

    public static string AxisCom;

    public static byte AxisAddress = 1;

    public static string Dummy;

    public static int rc;

    public static void Main()
    {
        Dummy = new string(' ', 1024);
        AxisCom = new string(' ', 1024);
        rc = autodetect_SearchAxis(false, AxisAddress, ref Dummy, ref AxisCom);
        Debug.WriteLine("rc: " + rc.ToString());
        Debug.WriteLine("AxisCom: " + AxisCom.ToString());
    }
}

这不是最大的接口规范。 从表面上看,调用者必须分配长度为1024的字符串缓冲区,并相信非托管代码不会超出该范围。 更好的接口是让调用者传递缓冲区及其长度,以便非托管代码可以确保其不会溢出缓冲区。

但是,假设您无法更改界面,则可以将其转换为以下形式:

[DllImport("autodetect.dll", CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi)]
public static extern int autodetect_SearchAxis(
    bool onusb, 
    byte searchsubaddress, 
    StringBuilder portname, 
    StringBuilder devicelocation
);

您需要声明并分配StringBuilder实例:

StringBuilder portname = new StringBuilder(1024);
StringBuilder devicelocation = new StringBuilder(1024);

然后调用看起来像这样:

int retval = autodetect_SearchAxis(onusb, searchsubaddress, portname, devicelocation);
// check retval for errors

然后在两个StringBuilder实例上使用ToString()方法读取返回的字符串值。

我必须承认对于.net下的Declare工作方式有些不确定,因为它是旧VB6代码的向后兼容性支柱。 所以我确实想知道应该如何整理bool参数。 是1字节的布尔值还是4字节的布尔值? 就像在这个答案中写的那样,它被编组为默认的4字节Windows布尔值BOOL

我假设给您带来麻烦的一行(按问题的标题)是:

Public Declare Function autodetect_SearchAxis Lib "autodetect.dll" _
( _
    ByVal onusb As Boolean, _
    ByVal searchsubadress As Byte, _
    ByRef portname As String, _
    ByRef devicelocation As String _
) As Integer

在C#中,您需要添加一个引用(在静态类的顶部):

using System.Runtime.InteropServices;

然后,您需要进行相同的DLL导入:

[DllImport("autodetect.dll", SetLastError = true)]
public static extern int autodetect_SearchAxis
(
    bool onusb, 
    byte searchsubadress, 
    [MarshalAs(UnmanagedType.AnsiBStr)] ref string portname, 
    [MarshalAs(UnmanagedType.AnsiBStr)] ref string devicelocation
);

其余代码应该很简单。

要了解更多信息,请结帐:

暂无
暂无

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

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