Unable to link to a c++ dll from VB2019

Pages: 12
It won't give any errors because the IDE won't know about it. P/Invoke is a form of dynamic linking, so the compiler can't check if the DLL is correct. In exchange for that dynamism, you need to ensure that when you run the program the DLL is somewhere where the program will be able to find it, and that it actually exports the symbols that you declare with P/Invoke.
Do I still need to reference the dll from VB IDE? And this time with the extra lines of code on the VB side it will not throw the error when I do correct?

When I say reference from the VB IDE I mean in VB 2019 I click on Menu-> Project and then Add Reference and click on the dll in the C++ dir.

Or are you saying I DO NOT do this and just let the dynamic linking work on it's own without the IDE reference?
Last edited on
Do I still need to reference the dll from VB IDE?
It's still the same native DLL, so you'll still be unable to add it as a dependency in the project file. P/Invoke doesn't care about any of that, it just needs to be able to find the DLL when you execute the program.
I got some mixed progress going by your advice:

In my VB code:

Public Class MyProject

' Declare the P/Invoke signature for the DoubleValue function
<DllImport("RungeKutta.dll", CallingConvention:=CallingConvention.Cdecl)>
Private Shared Function RK_Animate(ByVal value As Double)
End Function

<DllImport("RungeKutta.dll", CallingConvention:=CallingConvention.Cdecl)>
Private Shared Function RK_Init() As Integer
End Function


Above I asked ChatGBT to help me with this topic of using p/invoke.

VB:
Private Sub MyProject_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

RK_Init()
RK_Animate(1)


On the C++ Side I have


in my RungeKutta.H

RUNGEKUTTA_API void RK_Animate(double TimeInterval);
extern RUNGEKUTTA_API void RK_Animate(double);

RUNGEKUTTA_API int RK_Init(void);
extern RUNGEKUTTA_API int RK_Init();


RungeKutta.CPP

// An exported function.
RUNGEKUTTA_API void RK_Animate(double TimeInterval)
{
/*
printf("RK_Animate version VS2010Express version TimeInterval = %f",TimeInterval);
if(RK_Universe->Size>0)
{
RK_Universe->Animate(TimeInterval);
}
else
{
printf("\nRK_Animate: Size = 0");
}
*/
}

RUNGEKUTTA_API int RK_Init()
{
static bool alreadycalled = false;
if (alreadycalled == false)
{
printf("\n==================== Hello THIS IS THE INIT FOR RK");

RK_Universe = new ObjectList;
RK_Universe->AddSystem();
printf("\nRK_Universe->Size = %d", RK_Universe->Size);
printf("\nRK_Universe->SizeGravitational = %d", RK_Universe->SizeGravitational);
printf("\nRK_Universe->SizeNonGravitational = %d", RK_Universe->SizeNonGravitational);

printf("\n==================== Hello THIS IS THE END OF INIT FOR RK");
alreadycalled = true;
return 11;
}
else
{
printf("\n==================== Hello THIS IS THE INIT FOR RK BUT ITS ALREADY CALLED SO NOTHING HAPPENED THIS TIME ROUND");
return 101;
}

}


For debugging purposes I have coment out code in the first function but I am still getting the following errors:



VB SIDE:

For RK_Init()

System.EntryPointNotFoundException
HResult=0x80131523
Message=Unable to find an entry point named 'RK_Init' in DLL 'RungeKutta.dll'.
Source=Part2
StackTrace:
at Part2.MyProject.RK_Init()
at Part2.MyProject.MyProject_Load(Object sender, EventArgs e) in C:\Users\david\OneDrive\WORKSPACE\VB\VB2019\REVAMP 6\MyProject.vb:line 280
at System.Windows.Forms.Form.OnLoad(EventArgs e)
at System.Windows.Forms.Form.OnCreateControl()
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.WmShowWindow(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.Form.WmShowWindow(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)




For RK_Animate(1)

System.Runtime.InteropServices.MarshalDirectiveException
HResult=0x80131535
Message=PInvoke restriction: cannot return variants.
Source=Part2
StackTrace:
at Part2.MyProject.RK_Animate(Double value)
at Part2.MyProject.MyProject_Load(Object sender, EventArgs e) in C:\Users\david\OneDrive\WORKSPACE\VB\VB2019\REVAMP 6\MyProject.vb:line 281
at System.Windows.Forms.Form.OnLoad(EventArgs e)
at System.Windows.Forms.Form.OnCreateControl()
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.WmShowWindow(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.Form.WmShowWindow(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


I don't know what to make of it. ChatBotGBT is no help here because it says to check the arguments which in this case are either void or integer.

HIGH REZ IMAGES:
https://drive.google.com/file/d/1ea7K-USS_Y4IkddRabALtp1FjMK9fvEp/view?usp=sharing

https://drive.google.com/file/d/1Ca5NBzuHHX4T_e6uRZus1kB55jU9f1Zf/view?usp=sharing

https://drive.google.com/file/d/159CQ4iQ-qHKdU7fv8F_UbG02BgX_-tBE/view?usp=sharing

https://drive.google.com/file/d/1vBkpyfD9TKcUHvFTt95mKQnSVvPch3yT/view?usp=sharing

https://drive.google.com/file/d/1lwpTE3Q9PcJeksnVj2CpoI7X5RDwNaRU/view?usp=sharing


On a side note Im hiring experts to help me with problems like this as a freelance consultant. Do let me know if you want paid work.
Last edited on
The linker is mangling the exported symbols. Name mangling is needed to support function overloading. To prevent this you need to tell the linker that it should treat them as part of a C interface:
1
2
3
4
5
6
7
8
9
10
11
extern "C"{

RUNGEKUTTA_API int RK_Init(){
    //...
}

RUNGEKUTTA_API void RK_Animate(double TimeInterval){
    //...
}

}
Alternatively you can include the extern "C" specification in the RUNGEKUTTA_API macro:
 
#define RUNGEKUTTA_API extern "C" __declspec(dllexport) 
Thanks for this useful reply,

I added this line

#define RUNGEKUTTA_API extern "C" __declspec(dllexport)

into RungeKutta.h

https://drive.google.com/file/d/1LsxGFz-BhSwTSUoM0ElyegUzIjrdANhj/view?usp=sharing

When I added the line it came into conflict with an existing #define that chatGBT created for me:
#ifdef RUNGEKUTTA_EXPORTS
#define RUNGEKUTTA_API __declspec(dllexport)
#else
#define RUNGEKUTTA_API __declspec(dllimport)
#endif

Im sorry but I know very little about precompilers. I tried to replace it with yours but it didnt work. What should I do?

WITH THE FIRST OPTION:

https://drive.google.com/file/d/16BGiRC_rwMe3pJWG_9X4gvyyQCCpJk1C/view?usp=sharing

https://drive.google.com/file/d/1RS7lwwzqxQ3ZpH7zHFqNsWG58rsxzvCi/view?usp=sharing

https://drive.google.com/file/d/1GK7fl_bbxD9Qdk7qiEeCE5GBlPD2OFey/view?usp=sharing

https://drive.google.com/file/d/1zHsAFvyAGDR06zyQvlNP-19HC6CSHmQG/view?usp=sharing

I added the code for DoubleNumber function just to keep things simple and I got error in VB as you will see in the above 4 screenshots. I had to comment out

RUNGEKUTTA_API double RK_DoubleNumber(double number);
extern RUNGEKUTTA_API double RK_DoubleNumber(double);

For your code to work. Perhaps thats the reason.
Last edited on
Replace the #ifdef block with
1
2
3
4
5
#ifdef RUNGEKUTTA_EXPORTS
#define RUNGEKUTTA_API extern "C" __declspec(dllexport)
#else
#define RUNGEKUTTA_API extern "C" __declspec(dllimport)
#endif 
and remove the new #define you just added.
Done, now I got this situation:

https://drive.google.com/file/d/1YcFZrHOJqwxLwGIKxmF09y4pWCM-ZCsk/view?usp=sharing

With VS2019:

https://drive.google.com/file/d/1nwD-ucykopcbiwlA_HwbxwpfEkhCLrXP/view?usp=sharing

AND

https://drive.google.com/file/d/1LWGnrCY6w2xi4JnZKX6fWwhC92rs_ePg/view?usp=sharing

May I suggest to help me, if any of you are able to write a small VSC++ project with pinvoke that has a function that simply doubles a number? And have it work in VB?

If you can do that can you send me the source code so I can use it as a template?

Im watching:
https://www.youtube.com/watch?v=hYZjhXkxT74
Now. Trying to see if this solution works. With this solution it says I need a def file. What a pain in the butt! There's no file to download from the youtube site. So will have to manually type everything!
Last edited on
If you're also exporting classes and other C++ stuff then revert the macro to what it was before and do the extern "C" { /*...*/ } thing. Remember to update both the declarations and the definitions of the functions you want to call from .NET.

You don't need a def file.
Hi all after, including the .def file in the youtube tutorial i managed to double a number in VB using a c++ dll. Thanks so much for your patience!

I noticed the last comment by helios says I dont need a def file, ill explore that also. Thanks so much but I think the hard part is behind me!
Topic archived. No new replies allowed.
Pages: 12