Library tutorials & articles
Calling a C++ DLL from Visual Basic
- Introduction
- Adding the files
- The VB Code
Introduction
There have been projects I have been on in the past where there was certain functionality I needed but could not get from VB, or I had to do a complete workaround to get the functionality I could get from C++ very easily. In this tutorial I will show you how to create a C++ dll that you can call from VB. I figure instead of doing the norm, "HELLO WORLD", or "ADD NUMBER", routine I will show you how to resolve a domain name to an IP address and return that IP address back to VB, this is a little advanced for the beginner but if you have some C++ experience it wont be that bad.
For this example I will be using VC++ 6 so if you have that IDE then you will be right at home and in the case you do not use that IDE then just try to follow along and enjoy the ride!
Ok, you will first have to create a new dynamic link library project. After you create this project you will be prompted on what kind of DLL, just click empty.
After that is complete you will have to add the library ws2_32.lib to the project under project-> settings -> link -> object/modules library or the code below will not compile! Believe me when I tell you this as I had the fun of learning this the hard way and it was a nightmare.
Related articles
Related discussion
-
VB6 Runtime error 381 subsript out of range Error
by Uncle (2 replies)
-
passing and reading parameters from using Shell
by jigartoliya (0 replies)
-
Convert C++ code to VB6
by mawcot (4 replies)
-
listbox scrollbar
by Dennijr (10 replies)
-
Can you describe Above simple VB6 code?
by pramodmca09 (0 replies)
Related podcasts
-
Christian Beauclair
14 mai 2008 (�mission #0074) ::.Christian Beauclair: Stratégies de migration VB6 vers .NET Nous discutons avec Christian Beauclair des stratégies de migration VB6 vers .NET. Entre autres, nous discutons comment utiliser le "VB 6 Code Advisor" et le "Interop Forms Toolkit" pour ajouter la puiss...
Hello, I found this article very interesting!
I'm trying to call some functions of a C++ DLL the same way you did in your article but I get an error that says "impossible to find the entry point for the function". I don't know why. Could you help me?
Thank you.
!--removed tag-->Your first stop for a healthy computer! Proccess information, driver downloads, dll files, information about virusses and pc manuals.
Check out this article:
http://blog.rednael.com/2008/08/29/MarshallingUsingNativeDLLsInNET.aspx
It's an in-depth article that shows you how to marshal any native (or C++) DLL. It shows which types are interoperable, how to import a DLL, how to pass strings and how to de-reference pointers.
It's quite easy.
thank you very much for this code. It resolves all my problems and errors. khalil from france.
This program is very useful for me, you are very terrific. Thanks
Hi Caripito,
I guess what you need is to see if there's some VBA function to return the location of the current workbook. I don't use Excel/VBA hardly at all, so I'm not familiar with any such function.
You say there is a "ThisWorkbook.Path" in Excel VBA? Seems like it would do what you need - what does it return? When you say it doesn't work for you, what is the error?
Cheers,
- Chuck Somerville
Public Declare Convert Lib "Blue.dll" (ByVal a as Byte) as Bool
---- where Convert is the function and Blue.dll is the DLL that have to be in System32 folder in Windows...
The problem is that I need to place the DLL in the same folder as the Workbook to make easy the installation and use, but I don't know how to write the sentence... In other situations I have used App.path or ThisWorkBook.path but in this declaration isn't work...
The program works perfectly when the DLL is in the Windows System32 folder... And if I write the whole path it works too, but the problem is that this path is not going to be always the same, because it depends on where the user place the folder...
So, if you happen to get the problem and have any clue, please write me as soon as possible...
Thanks again
Caripito
Hello... I have some similar troubles.. I need to declare a DLL in a MACRO in EXCEL using Visual Basic, and I need to set the default path in the same path the WORKBOOK is... Can you please help to do that?... I have tried everything but Visual Basic always pop up an ERROR...
Thanks a lot...
Caripito
Well, VBA within Excel is not the same as a stand-alone VB program with an installer. My previous comments relate to having the installer install the app and the DLL.
There is one way to "hook up" your VBA app to some DLLs (ones that provide "object libraries" to "Automation Controllers" like Visual Basic, having been registered as such with Windows). Search the VBA help for the topic called "Check or Add an Object Library Reference" to see how to add a reference to a DLL which has had an "object library" or a "type library" registered with Windows.
I believe you can also use a "Declare" statement to name a DLL which has been written to be callable from VB, but the location is going to have to be one of the places I mentioned earlier, and the location of the workbook is not in the DLL search path. (The workbook is not "executing" - Excel, including VBA within Excel, is executing from the directory where Excel.EXE lives.) Look in VBA help for the "Declare Statement" topic.
Both the above topics can be found in the help if you go to the "Index" tab and enter "DLL" in the "Keywords" area.
- Chuck Somerville
Thanks a lot...
Caripito
I found this article extremely helpful. It was exactly the right level of detail. However, is it necessary to put the path to the dll in your vb code? Isn't it more common to put the dll in a folder that windows knows about (for example on my Widnows 2000 machine, there's hundreds of dll's in my Windows\System32 folder). This way we could just have vb find the dll with the name cdll4_vb.dll. The reason I ask is that I may deploy this to other versions of Windows, and I'm concerned that other versions of Windows keep their DLL files in a different location.
You can install the DLL in the directory you install the VB app into, if it's a DLL only you will need.
You can install it to the windows\system32 directory if it is a DLL shared by other apps.
When you run the Package and Deployment Wizard in VB to make your installer, you get to specify details about the DLL, like where to install it ({appdir} or {win\sys32} or something like that - it's a pull-down with symbols for those locations so the installer will point it all to the right place at each installation). You also get to say whether it's a DLL that may be shared by other apps. If so, it won't be un-installed untill all the other apps that use it are uninstalled as well.
Your app will find the DLL in either location... DLL search rules are a little like .EXE program search rules in DOS...
1. look in the dir your program launched from.
2. look in every location in the PATH.
3. look in the windows directory (not necessarily named C:\windows).
4. look in the windows\system32 directory.
There's pretty good help on all this in the VB6 help system.
- Chuck Somerville
I found this article extremely helpful. It was exactly the right level of detail. However, is it necessary to put the path to the dll in your vb code? Isn't it more common to put the dll in a folder that windows knows about (for example on my Widnows 2000 machine, there's hundreds of dll's in my Windows\System32 folder). This way we could just have vb find the dll with the name cdll4_vb.dll. The reason I ask is that I may deploy this to other versions of Windows, and I'm concerned that other versions of Windows keep their DLL files in a different location.
I'm pretty sure strings are handled differently in VB than in C++.
Thank you very much, your article help me so much. I create the 3 files that you recomended and put the code into the files and after I go to the Visual Basic and put the code, and when I run program, image what happen!!!! It run perfectly.
Well, thank you very much again, and if you need something only ask me.
Regards,
Wilton Filho
Hi,
I am trying to invoke a VB application from C++ dll using the ShellExecuteEx command. The problem is when I execute the program, the VB application comes up, but when I try to move the form, the parent window goes blank. Same thing happens if I switch between windows. Can anyone please guide me how to invoke a VB application from a C++ dll without much changes to my existing code.
Snippet of my code:
HWND lhwndFound;
LPSHELLEXECUTEINFO lsei=new SHELLEXECUTEINFO;
lhwndFound=GetActiveWindow();
if(lhwndFound != NULL)
{
lsei->cbSize=sizeof(SHELLEXECUTEINFO);
lsei->fMask = SEEMASKNOCLOSEPROCESS;
lsei->hwnd =lhwndFound;
lsei->lpVerb = "open";
lsei->lpFile = "MyApplication.exe";
lsei->lpParameters = "Src";
lsei->lpDirectory = lconfigpath;
lsei->nShow = SWSHOWNORMAL;
lsei->hInstApp = NULL;
ShellExecuteEx(l_sei);
WaitForSingleObject(lsei->hProcess , INFINITE);
delete lsei;
}
Thanks in advance
Regards,
Rashmi
Under the "Link" tab:
In the "General" category, enable "Generate debug info".
In the "Debug" category, enable "Debug info".
Under the "C++" tab:
In the "General" category, enable "Generate browse info", and set the "Debug Info" to "Program Database for Edit and Continue".
In the "C++ Language" category, enable "Enable exception handling".
In the "Listing Files" category, enable "Generate browse info".
Under the "Browse Info" tab:
Enable "Build browse info".
Then just use the Debug version instead of the release version and you can step through on errors.
Note that if you want to step through part of the code even if it doesn't generate an error, just add VERIFY(0); wherever you want to step through.
John
Thanks, it was a very usefull for me.
However I still have one problem...
I'm working with Visual Studio .Net, and I want to debug both, the C++ DLL and the Visual Basic application at once.
The C++ DLL in the article is linked to the applications in a 'dynamic link', that is simmilar to calling LoadLibrary from a C++ application. Is there a 'static link' way as well?
i.e. is there a way to link the .lib file of the DLL to the Visual Basic application, so that when reaching the call to the C++ function when debugging the Visual Basic application, it will be possible to step in to the C++ code etc?
Thanks in advance
Israel
declare the DLL functions as "Private" within a module, you won't be able to call them
directly from any other place. VB complains "Sub or Function not defined"... for what it's worth.
Linking...
Creating library Release/Dll.lib and object Release/Dll.exp
Dll.obj : error LNK2001: unresolved external symbol _inet_ntoa@4
Dll.obj : error LNK2001: unresolved external symbol _inet_addr@4
Dll.obj : error LNK2001: unresolved external symbol _gethostbyname@4
Dll.obj : error LNK2001: unresolved external symbol _WSACleanup@0
Dll.obj : error LNK2001: unresolved external symbol _WSAStartup@8
Release/Dll.dll : fatal error LNK1120: 5 unresolved externals
Error executing link.exe.
http://www.mvps.org/vcfaq/il/3.htm actually deals with one of the problems mentioned. Not sure whether a wrapper can be written in this case ...
dwilson
How to include dll file in visual basic 6.0 program?
Thanks in advance
bloodlustangel
I am use studio to do the coding and prompt out this exception
An unhandled exception of type 'System.DllNotFoundException' occurred in WindowsApplication1.exe
Additional information: Unable to load DLL (C:\jacky\JavaTest\extendDLL\Debug\extendDLL.dll).
but it is there already
I'd bet it had something to do with the following:
http://www.mvps.org/vcfaq/il/2.htm
Since you don't have the source of the DLL that you can not change this directly but you could wrapper the _cdecl declared DLL in a C++ object which is declared as _stdcall .
have you discovered how to solve the problem of the entry point? Would be appreciative if you could share with me.
Cyndi
I tried the code and found it working OK.
but what my problem is that i have to call DLL functions (dll provided by the card manufacturere) of a PCI card from my VB code.
I adopted the same code with some modification to test a single function of dll and it works but the function while in execution throws an exception and pops up a message that PCI-XXX card not found.
while that same dll function is working properly when used in a sample program in VC++ (provided by the manufacturer).
so can any body tell me that how to debug a dll so that i can rectify the problem.
everything seems to work. But when I run VB nothing really happens. I just get a blank window box. I think my VB isn't set up right. All I did was copy and paste the code into my VB code form. I didn't set up any buttons or text boxes. Am I supposed to?
Please help. THanks!
I think this article is very useful to me, as a new vb programmer, however, i got this message when i run the VB
'Bad dll calling conversion'
do anyone know what is the reason?
I have very basic knowledge in Visual C++.I created the dll file and it is correctly compiled.
But when i execute my vb program,I'm getting an error.......Can't find dll entry point ResolveNameTo_In.
Please help
Can i do a *.dll in Borland c/c++ 3.0 , (dos) , i want to make want to use all the port of my PC ( COM1 , LPT1, USB , etc.
I have a problem , i dont know how to make it , can you tell me how ?
Thanks
Actually you can call a .dll in VBScript, however I am not sure that you can create them like this in C++ (maybe you can, I haven't done it that way exactly). You need to create an ActiveX Dll in Visual Basic, simply write a function, then goto File and compile your .dll. Remember the class and project name. In ASP you can do something like this.
<%
Dim x
Set x = Server.CreateObject("Project1.Class1")
If x.Check(1) = 1 Then
Response.Write("Correct")
End If
Set x = Nothing
%>
Hope This Helps
Can a dll which is created using _cdecl be used in VB
I have the following code:
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ulreasonfor_call,
LPVOID lpReserved
 
{
return TRUE;
}
extern "C" __declspec(dllexport) bool a(char* lpszPathName)
{
....
....
}
I called the dll CVB.dll, i made a CVB.DEF file "
LIBRARY C_VB
DESCRIPTION 'A C++ dll that can be called from VB'
EXPORTS
ResolveNameToIp @1
" and no go, says it cannot find the entry point "ResolveNameToIp".
I got by this problem by using dllexport and the extern "C" prefix, no need for a .DEF file?
Secondly Subs work fine under this method, however when I do get a function to 'work' it doesnt, tells me bad calling procedure, I had thought perhaps the [extern "C"] and different calling convention of dllexport [declspec( dllexport )] were responsible but when I use [stdcall] same problem. I suppose im on my own to sort that out.
got it working via the PASCAL calling convention..
///snippet
(Error 49)
Your program is calling a routine in a dynamic-link library (DLL) that either is being passed the wrong type or number of arguments or does not use the Pascal calling convention. Make sure that the arguments passed to the DLL routine exactly match the arguments expected by the routine. If the DLL routine expects arguments by value, then make sure ByVal is specified for those arguments in the declaration for the routine.
snippet///
extern "C" <return-type> __declspec( dllexport ) PASCAL func(...)
perhaps thats useful to someone who runs across the same problems as I.
Hi all,
'How do I create a dll in C++ and call it from VB?' was an article which can be called Simply SUPERB by its simlicity and elegance. Very helpful and informative.
Thank you Kevin Saitta. It was a nice work.
Regards,
Jeri.
You can't call a DLL from VBScript, needs to be VB or VBA.
Regards,
Shifty
Here is the ASP code:
<HTML>
<HEAD>
<TITLE>Testing page</TITLE>
</HEAD>
<BODY>
<%
Private Declare Function Check _
Lib "D:\inetpub\H63080\TryItOut\Debug\TryItOut.dll" _
(ByVal input As Integer) As Integer
Private Sub test()
If Check(1)=1 Then
Response.Write "Correct."
End If
End Sub
%>
</BODY>
</HTML>
Can anyone help me out in this? Thanks a lot!
very nice article, thank you. but it's not really c++ with object et al. i would love to know how to instantiate objects in vb whose underlying classes are defined and implemented in a c++ dll.
lol .. oh well
Never mind...I didn't see the text ResolveNameTo_Ip. Now it all makes sense!!
As far as I am aware, the declaration would be valid providing there was a function called "ResolveNameTo_IP" matching the declaration in the DLL.... however, I'm not quite sure how functions in different classes come into the api declarations....
What if there were more than one function available? Would the above VB declaration still been valid?
Surely "Declare Function ResolveNameTo_Ip" is telling VB that there is a function with that name in the DLL? If there is no Alias attribute, VB assumes that the function declaration is the same as in the DLL......
I love reading articles that the source code actually works on. One thing...
Private Declare Function ResolveNameToIp _
Lib "C:\Program Files\Microsoft Visual Studio\MyProjects\cdll4vb\Debug\cdll4_vb.dll" _
(ByVal pcDomainToResolve As String, _
ByVal szReturnIP As String, _
ByRef iSize As Integer) As Long
How did VB know there was a function called ResolveNameTo_Ip available int he DLL. I understand the .def file indicated it, but in most win32 declarations the function name would have been included. If you notice above, it wasn't in this case?
Just what I was looking for!
This thread is for discussions of Calling a C++ DLL from Visual Basic.