【问题标题】:Translate this DLL include from VB.net to C#将此 DLL 包含从 VB.net 转换为 C#
【发布时间】:2015-10-07 15:35:38
【问题描述】:

这已经被问了一百万次了,但我仍然无法让它工作。所以我问: 我有一个 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

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

编辑:

我现在有了DLL函数的签名:

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

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

【问题讨论】:

  • 为什么不试试 VB.NET 到 C# 的转换器? =3
  • 你有没有调用函数的示例C++代码
  • 不幸的是,@RayKoopa 代码转换器并非没有缺陷。由于这里涉及到一个 dll 导入,如果代码转换器确实有效,我会感到有点惊讶。
  • 我已经用 DLL 的签名/声明和问题描述更新了我的问题。希望有人有更多的建议。谢谢!
  • @packoman 你能在这里找到解决方案吗?如果您能接受答案,那就太好了。

标签: c# c++ .net vb.net dllimport


【解决方案1】:

基本上应该是:

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());
    }
}

【讨论】:

  • 该死!你用几秒钟就打败了我! :( 但有一件事,你不需要 rc.ToString() 和 AxisCom.ToString()。这些是完全多余的 :-)
  • ref string 不会工作。你怎么能指望非托管函数创建一个 .net 字符串。
  • ref string 将起作用(至少与在 VB 中一样),请参阅我的答案以了解如何。 --(另外,它不需要创建它——它是ref,而不是out——如果它正在创建字符串,我们应该将它标记为out)。
  • 完美答案。很高兴你包含了using System.Runtime.InteropServices;
  • @BrainSlugs83 不,我认为您不了解互操作的工作原理。然后假设我们假设调用者创建了字符串。那么非托管代码将如何处理 .net 字符串?
【解决方案2】:

这不是最大的接口规范。从表面上看,调用者必须分配长度为 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()方法读取返回的字符串值。

我必须承认对于Declare 在.net 下的工作方式有点不稳定,因为它是旧VB6 代码的向后兼容拐杖。所以我想知道应该如何编组bool 参数。它是 1 字节布尔值还是 4 字节布尔值?如本答案所述,它被编组为默认的 4 字节 Windows 布尔值 BOOL

【讨论】:

  • 是的,我也有很多未解决的问题。所以我懒洋洋地笨拙地翻译了VB.Net代码。
【解决方案3】:

我假设给你带来麻烦的那一行(根据问题的标题)是:

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
);

其余的代码应该很简单。

如需了解详情,请查看:

【讨论】:

  • ref string 错误,AnsiBstr 错误,SetLastError` 错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-09
  • 1970-01-01
  • 2012-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多