如何使用ANSI C字符串“char *”导入和调用非托管C DLL VB.NET的指针字符串? [英] How do I import and call unmanaged C dll with ANSI C string "char *" pointer string from VB.NET?

查看:184
本文介绍了如何使用ANSI C字符串“char *”导入和调用非托管C DLL VB.NET的指针字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了我自己的函数,这在C中将被声明为这样,使用标准的 Win32 调用约定:

  int Thing(char * command,char * buffer,int * BufSize); 

我有以下数量的Visual Basic代码,应该导入DLL文件并调用功能,包装它使它很容易调用Thing(CommandHere,GetDataBackHere)。



更新:此代码现在是一个工作的解决方案,如下所示: / p>

 导入Microsoft.VisualBasic 
导入System.Runtime.InteropServices
导入系统
导入系统。文本

命名空间dllInvocationSpace

公共类dllInvoker

'我尝试过属性,但是我无法建立它:
'< DllImport(thing1.dll,False,CallingConvention.Cdecl,CharSet.Ansi,Thing,True,True,False,True)>
声明Ansi函数Thing Libthing1.dll(ByVal Command As String,ByRef Buffer As StringBuilder,ByRef BufferLength As Integer)As Integer

'这部分由有用的用户贡献:
共享函数dllCall(ByVal Command As String,ByRef Results As String)As Integer
Dim Buffer As StringBuilder = New StringBuilder(65536)
Dim Length As Integer = Buffer.Capacity
Dim retCode作为Integer = Thing(命令,缓冲区,长度)
结果= Buffer.ToString()
'Debug.Assert(Results.Length = Length)'这个断言对我来说不是真的
返回retCode
结束函数

结束类

结束命名空间

我通过按照这里收到的帮助得到代码,然后我忘了 As Return Type (这让我有一个MarshalDirectiveException PInvokeRestriction)。然后我的DLL中断言失败,导致SEHException。一旦修复,这可以BEAUTIFULLY。谢谢你们有人在说这是不可能的新闻组,Visual Basic只加载托管的DLL程序集(我猜这是大多数Visual Basic用户常用的)。

解决方案

这取决于你如何使用C代码中的缓冲区参数。如果你只是把你的VB.NET代码 的字符串传递给你的C代码,然后声明ByVal String就够了。然而,如果您让C代码在缓冲区中返回一个字符串,则必须声明它ByVal StringBuilder并在调用之前正确初始化它。例如:

 公共类dllInvoker 
声明Ansi函数Thing LibThing1.dll(ByVal Command As String, ByVal缓冲区作为StringBuilder,ByRef BufferLength As Integer)As Integer

共享函数dllCall(ByVal Command As String,ByRef Results As String)As Integer
Dim Buffer As StringBuilder = New StringBuilder(65536)
Dim Length As Integer = Buffer.Capacity
Dim retCode As Integer = Thing(命令,缓冲区,长度)
结果= Buffer.ToString()
Debug.Assert(Results。长度=长度)
返回retCode
结束函数
结束类

请注意返回的长度值中的歧义。


I have written my own function, which in C would be declared like this, using standard Win32 calling conventions:

int Thing( char * command, char * buffer, int * BufSize);

I have the following amount of Visual Basic code figured out, which should import the DLL file and call this function, wrapping it up to make it easy to call Thing("CommandHere",GetDataBackHere).

UPDATE: This code is now a working solution, as shown here:

Imports Microsoft.VisualBasic
Imports System.Runtime.InteropServices
Imports System
Imports System.Text

Namespace dllInvocationSpace

    Public Class dllInvoker

        ' I tried attributes, but I could not make it build:
        ' <DllImport("thing1.dll", False, CallingConvention.Cdecl, CharSet.Ansi, "Thing", True, True, False, True)>
        Declare Ansi Function Thing Lib "thing1.dll" (ByVal Command As String, ByRef Buffer As StringBuilder, ByRef BufferLength As Integer) As Integer

        ' This part contributed by helpful user:
        Shared Function dllCall(ByVal Command As String, ByRef Results As String) As Integer
            Dim Buffer As StringBuilder = New StringBuilder(65536)
            Dim Length As Integer = Buffer.Capacity
            Dim retCode As Integer = Thing(Command, Buffer, Length)
            Results = Buffer.ToString()
            'Debug.Assert(Results.Length = Length)  ' This assertion is not true for me
            Return retCode
        End Function

    End Class

End Namespace

I got the code to build by following the help received here, and then I had forgot the As Return Type (which got me a MarshalDirectiveException PInvokeRestriction). Then I had an assertion failure inside my DLL, which lead to an SEHException. Once fixed, this works BEAUTIFULLY. Thank you folks. There are newsgroups where people are saying this can not be done, that Visual Basic only loads managed DLL assemblies (which I guess is the normal thing most Visual Basic users are used to).

解决方案

It depends on how you use the buffer argument in your C code. If you only pass a string from your VB.NET code to your C code then declaring it ByVal String is good enough. If however you let the C code return a string in the buffer then you have to declare it ByVal StringBuilder and initialize it properly before the call. For example:

Public Class dllInvoker
    Declare Ansi Function Thing Lib "Thing1.dll" (ByVal Command As String, ByVal Buffer As StringBuilder, ByRef BufferLength As Integer) As Integer

    Shared Function dllCall(ByVal Command As String, ByRef Results As String) As Integer
        Dim Buffer As StringBuilder = New StringBuilder(65536)
        Dim Length As Integer = Buffer.Capacity
        Dim retCode As Integer = Thing(Command, Buffer, Length)
        Results = Buffer.ToString()
        Debug.Assert(Results.Length = Length)
        Return retCode
    End Function
End Class

Note the ambiguity in the returned Length value.

这篇关于如何使用ANSI C字符串“char *”导入和调用非托管C DLL VB.NET的指针字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆