Calling Unmanaged DLL from VB - vb.net

I'm having some trouble finding the syntax for making function calls to unmanaged DLLs in VB.NET. Is anyone familiar with this?
Let's just assume there's a function "Connected" in unmanaged DLL "Connector.DLL". I want to call this function by creating an abstract function call to it.
I've seen some code out there that looks something like
[DllImport("Connector.DLL")]
Public Shared Function Connect(ByVal intPort)
But that syntax doesn't work for me.

Try the following code.
Public Declare Function Connect Lib "Connector.DLL" (<MarshalAs(UnmanagedType.I4)> ByVal intPort As Integer) As Integer

In Visual Studio, add a reference to this Dll.
In Code:
Dim vr as new COMDllClass()
vr.FunctionInDll()
EDIT per comment:
Try this code:
<DllImport("Connector.DLL")> _
Public Shared Function Connect(ByVal intPort)

Related

vb.net: How to Structure to IntPtr

I have a vb6.0 (basic) project which I want to migrate to the new vs2022.
Most of the code just translated "more or less" fine, but there are some open points. I tried checking internet, but I couldnt find solution.
So here is my issue:
I have following code:
Public Structure Test
Dim a as long
Dim b as long
....
End structure
Public Sub xyz()
'here im filling Test structure locally
a = test...
..
A(a)
End sub
external dll function I want to call is A([In] IntPtr Data)
so the calling of A with my Test structure is failing, in vb6.0 it was working fine. I am not sure whats the problem. I tried some things, but I have no clue
I expected that it can just compile like its comiling in vb6.0. I have not touched any of this code part yet.
Another thing is that VarPtr() function is not available anymore. What could be the replacement in vs2022?
When I need to pass a structure to an unmanaged API as a pointer Intptr, I would do the following:
Allocate unmanaged memory of the size of the structure. Dim buffer As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(T)))
Pass the structure pointer to the unmanaged API.
When the unmanaged methods returns, converts the pointer to the structure using: Marshal.PtrToStructure(Of T)(buffer)
Do not forget to free the previously allocated unmanaged memory
Marshal.FreeHGlobal(buffer)

Access .dll library MODULE function in Excel (VBA)

I have a library called PIT_math_tools (written in vb.net) containing math functions which is split up into different modules.
In this case, the function I want to access is located in a Module called geometry_ellipsen_module:
Namespace geometry_ellipsen
Public Module geometry_ellipsen_module
...
Public Function calc_distanz_ellipse_kreis(...) As Double
Now I want to access the Function calc_distanz_ellipse_kreis() in VBA.
I used the following declare statement to accomplish this:
Private Declare PtrSafe Function calc_distanz_ellipse_kreis Lib "C:\Users\path...\PIT_math_tools.dll" (...) As Double
So far, everything looks fine.
When trying to call that function, however, I get runtime error '453'
"DLL-Entry Point calc_distanz_ellipse_kreis in 'PathToLibrary' not found."
When using the function in other .Net code, it could be found either by using the prefix
PIT_math_tools.geometry_ellipsen.geometry_ellipsen_module.calc_distanz_ellipse_kreis()
or an import statement identical to the prefix above.
Based on that, I tried extending the Function name in the Declare Statement by the same prefix:
Private Declare PtrSafe Function geometry_ellipsen.geometry_ellipsen_module.calc_distanz_ellipse_kreis Lib ...
However, this results in a compiler error "Expected: Lib".
How do I get the vba code to find the function inside the library module?
Thanks in advance.
The VBA syntax...
Private Declare Function SomeMethod() Lib "Some.dll"
... is used to prototype standard Win32 DLLs, e.g. Win32 API. Which .NET DLLs (aka "Assemblies") are not.
What you need to do in VB.NET is to make that assembly COM-visible. VB.NET creates a typelib (*.tlb) for the assembly.
In VBA you then add a COM reference (point to that typelib) to your project like you would do with other COM DLLs (ADODB, MSXML etc.). And then you do your standard
Dim myObject As Namespace.ClassName
Set myObject = New Namespace.ClassName
With myObject
.ThisProperty = 123
Dim lRet As Long
lRet = .ThisMethod("abc")
End With

"Set" and explicit "Variant" statement Deprecation?

I am relatively new to programming in VB, so please be patient with my frustration.
I am trying to declare a class using VB in Visual Studio 2010 Ultimate, and I'm following along with a tutorial, but Intellisense keeps messing with my code. Here's something along the lines of what I'm trying to write:
Import HYSYS
Dim myVar As Variant
...
Public Class MyClassVB1
Dim hyContainer As Object
Public Function Initialize(ByVal Container As Object, ByVal IsRecalling As Boolean) As Long
Set hyContainer = Container
End Function
However, Visual Studio turns my code into this:
Import HYSYS
Dim myVar As VariantType
...
Public Class MyClassVB1
Dim hyContainer As Object
Public Function Initialize(ByVal Container As Object, ByVal IsRecalling As Boolean) As Long
SetAttr() hyContainer = Container
End Function
After arguing with Visual Studio for a while, I finally have the message Let and Set assignment statements are no longer supported.
Is there a replacement that I'm supposed to use, or does Visual Studio just assume that I mean Variant if I don't explicitly specify a type?
Likewise, do I need to use a keyword or function for variable assignment, or can I treat it like I would in c++ and just write hyContainer = Container?
Set, as you're using it, is left over from the vb6/vbscript days.
It no longer works like that in VB.Net. You never ever use it for assignment.
You may be following an obsolete tutorial. In VB.Net, Set is only used as part of a LINQ query.
Variant is similar. It is no longer part of the VB language at all, and has not been for more than 10 years.

Visual C++ managed app: Unable to find an entry point named 'Add'

I have followed the tutorial on the following page to create a c++ DLL and I have put it in the System32 folder: http://msdn.microsoft.com/en-us/library/ms235636%28v=vs.80%29.aspx. I am able to run the .exe from anywhere on the PC. Now I want to be able to call Add from a VB.NET application, so I have added the following code:
Imports System.Runtime.InteropServices
Public Class Form1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Try
Dim Test As Integer
Test = Add(1, 1)
MsgBox(Test)
Catch ex As Exception
End Try
End Sub
<DllImport("MathFuncsDll.dll", EntryPoint:="Add", SetLastError:=True, CharSet:=CharSet.Ansi)> _
Private Shared Function Add(ByVal a As Double, ByVal B As Double) As Double
End Function
End Class
I get the following error: Unable to find an entry point named 'Add' in DLL 'MathFuncsDll.dll. I believe this is because of the namespace. I have researched this and some web pages say namespaces are not allowed with Platform Invoke and some web pages say they are allowed. What is the problem?
The entry point is not named "Add". From the Visual Studio Command Prompt, run dumpbin /exports MathFuncsDll.dll to see the exported names. To get this declaration:
<DllImport("MathFuncsDll.dll", EntryPoint:="?Add#MyMathFuncs#MathFuncs##SANNN#Z", _
CallingConvention:=CallingConvention.Cdecl)> _
Private Shared Function Add(ByVal a As Double, ByVal B As Double) As Double
End Function
The strange looking name is produced by the C++ compiler, a feature called "name decoration". It supports function overloading. You can put extern "C" in front of the function declaration to suppress it. It is actually better if you don't. Also note that SetLastError wasn't correct, the code doesn't actually call SetLastError() to report errors. And CharSet wasn't appropriate, these functions don't take strings.
You'll also need to do something about the Divide function, throwing a C++ exception won't come to a good end in an interop scenario, only C++ code can catch the exception.
Namespaces are not allowed. PInvoke works like plain C client. Don't forget also to declare MathFuncsDll as extern "C" to prevent C++ name mangling. Use Dependency Walker or dumpbin to see list of functions exported from MathFuncsDll.

Issue in calling VB6 native dll from VB.net Project

I have a vb6 project in which I use a dll library to do some tasks. For that, I add a module which declares all functions of that library such as:
Declare Function myFunction Lib "abcdapi.dll" (ByVal hVar1 As Long, ByVal hVar2 As Long) As Long
When I call this function (and many other similar) I'm able to do the work and correct Long pointer is returned. But when I try to do the same thing by VB.net (by importing the same library using dllimport and calling the same function), I get no result. although it does return some pointer but that doesn't produce correct result.
Private Const ABCD As String = "abcdapi.dll"
<DllImport(ABCD)>
Public Shared Function myFunction(ByVal hVar1 As IntPtr, ByVal hVar2 As IntPtr) As IntPtr
End Function
When I try to call the above function, it doesn't work. I even tried creating a dll in my vb6 project using the function and try to use imports keyword to call that new dll but that doesn't work either. What could be the issue and how do I make it work.
The docos you referenced show:
TM1IMPORT TM1_BOOL TM1API TM1ValBoolGet(TM1U hUser, TM1V vBool );
Is it possible that TM1U and TM1V are defined as 32 bit data types in that API and you are running your .NET code on a 64 bit machine, making your IntPtr a 64 bit data type? (If the API came with C header files you can see how those data types are defined). Try recompiling your .NET code to "x86" and try it again.
I just copied this code from your comment above:
the function call is below:
ibOK = TM1ValBoolGet(hUser, voTemp)
In VB.net: <<< I assume here you meant VB6
Declare Function TM1ValBoolGet Lib "tm1api.dll" (ByVal hUser As Long, ByVal vBool As Long) As Integer
In vb.net:
<DllImport(TM1APIDLL)> Public Shared Function TM1ValBoolGet(ByVal hUser As IntPtr, ByVal vBool As IntPtr) As Integer
End Function
It is probably a typo, but that return type in your VB6 is not the same as the one in VB.NET. A VB6 Integer is 16 bits and an Integer in VB.NET is 32 bits.