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

将此DLL包含从VB.net转换为C#,c#,c++,.net,vb.net,dllimport,C#,C++,.net,Vb.net,Dllimport,这个问题已经被问了一百万次,但我仍然无法让它发挥作用。所以我问: 我有一个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 portn

这个问题已经被问了一百万次,但我仍然无法让它发挥作用。所以我问: 我有一个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#代码尝试,但我使用
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());
    }
}

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

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

然后需要进行相同的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
);
代码的其余部分应该非常简单

要了解更多信息,请签出:


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

但是,假设您无法更改接口,您可以将其转换为以下内容:

[DllImport("autodetect.dll", CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi)]
public static extern int autodetect_SearchAxis(
    bool onusb, 
    byte searchsubaddress, 
    StringBuilder portname, 
    StringBuilder devicelocation
);
int retval = autodetect_SearchAxis(onusb, searchsubaddress, portname, devicelocation);
// check retval for errors
您需要声明并分配
StringBuilder
实例:

StringBuilder portname = new StringBuilder(1024);
StringBuilder devicelocation = new StringBuilder(1024);
然后这个电话看起来像这样:

[DllImport("autodetect.dll", CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi)]
public static extern int autodetect_SearchAxis(
    bool onusb, 
    byte searchsubaddress, 
    StringBuilder portname, 
    StringBuilder devicelocation
);
int retval = autodetect_SearchAxis(onusb, searchsubaddress, portname, devicelocation);
// check retval for errors
然后在两个
StringBuilder
实例上使用
ToString()
方法读取返回的字符串值


我必须承认,在.net下,
Declare
是如何工作的,我有点犹豫,因为它是旧VB6代码的向后兼容性支柱。因此,我确实想知道应该如何编组
bool
参数。它是一个1字节的布尔值,还是一个4字节的布尔值?如本答案中所述,它被封送为默认的4字节Windows布尔值,
BOOL

为什么不试试VB.NET到C的转换器呢=3是否有任何调用C++的C++代码示例function@RayKoopa不幸的是,代码转换器并非没有陷阱。由于这里涉及到dll导入,如果代码转换器真的能工作,我会有点惊讶。我已经用dll的签名/声明和问题的描述更新了我的问题。希望有人有更多的建议。谢谢@帕科曼,你能在这里找到解决办法吗?如果你能接受答案那就太好了。该死!你用几秒钟就赢了我(但有一件事,您不需要rc.ToString()和AxisCom.ToString()。它们是完全冗余的:-)
ref-string
不起作用。您怎么能期望非托管函数创建.net字符串。
ref-string
将正常工作(至少和VB中的一样好),请参阅我的答案以了解如何操作。-(而且,它不需要创建它——它是
ref,
而不是
out
——如果它正在创建字符串,我们应该将它标记为
out
)。完美的答案。很高兴您使用System.Runtime.InteropServices提供了
@brainslaugs83不,我认为你不了解互操作的工作原理。然后假设我们假设调用者创建了字符串。那么,非托管代码将如何处理.net字符串呢?
ref字符串
是错误的,
AnsiBstr
,SetLastError也是错误的。是的,这些都是我还有很多未解决的问题。所以我懒洋洋地翻译VB.Net代码。