How to create a BASIC dll to use in a C++ code?

Hi guys,

Forgive me if there is a topic similar to this already. I couldn't find one that helped me.

So, here is the thing: I'm developing a program in C++, in a Windows XP 32 bits platform, that needs to communicate with a program written in BASIC language (yes, pure BASIC, not VB). For that, we planned to create a dll containing some of the procedures we need from the code written in BASIC and call them in our C++ code using the dll.

We made a test using Visual Basic 2008 to create the dll and compiling the C++ program with Visual C++ 2008. It worked fine when we ran it in the local machine, but when we tried to run in another machine with the same configuration (just running the .exe file without compiling the program again, wich should work in machines with same configuration) it didn't work. It seems to me that we need to install Visual Studio in every machine we plan to run the program, wich is not an option for us here.

So, I'd like to know from you how can we create the DLL with the BASIC procedures and how to use these procedures within the C++ code. It would be better if it could be done without using Visual Studio, or at least in a way that don't forces us to install it in every machine that will run the program.

Can any one help me?

Thanks in advance,

Leonel
There are a couple of possibilities.

1. You probably don't have the runtime libraries on the other machine. Maybe you've done a debug build and not a release build. It's more likely that release versions of the C++ runtime are available.

2. The side-by-side thing in VS2005+ may require you to install the your component. But in my experience, it is possible to place a copy of your release-build DLL in the EXE's directory and that should be enough. It's not enough for a debug-build DLL though.
or try the static linkage option in your visual studio project preferences...
Ok, but how can I do a release build?

The way I created the DLL was just clicking at "File -> Make Project1.dll..." in Visual Basic 6.0 (not 2008 as I had mentioned).

Thanks again,

Leonel
If you can afford US $49 PowerBASIC is selling their 32 bit version 8 compiler (the newest version is 9) for that reduced price, and it'll easily produce a dll easily readable from your C++ program. Here is the link if interested...

http://www.powerbasic.com/

To create a dll all you would need to do is put the procedures in a code file with the 'Export' keyword appended, and...

#Compile Dll

A procedure would look like this...

Function SomeFunction As Long Export
....
....
End Function

Here...

http://www.jose.it-berater.org/smfforum/index.php?board=380.0

I've a lot of tutorials on mixed language programming between C++ and PowerBASIC using dlls created in both languages. Look at ProgEx13 through ProgEx19.

Last edited on

Ok, but how can I do a release build?

The way I created the DLL was just clicking at "File -> Make Project1.dll..." in Visual Basic 6.0 (not 2008 as I had mentioned).

Thanks again,

Leonel


Things can get a bit 'dicey' with VB6. Probably the VB6 runtime isn't on the machines you are testing. If you have the Professional or Enterprise Edition of VB6 you could create an installation program to install the VB6 created Dll. That would have to be done then on every machine where you would need to access it. Then you would be able to load it with your C++ program. It might be possible to just copy the VB6 runtime to the other machines. I forget, really. Its probably a couple megabytes you know (VB6 runtime).

That's the beauty of the PowerBASIC created Dll as I described above. No runtime dependencies. All you would need to do is put the dll somewhere in the Dll load PATH and you would be good. Depending on how much code you have the dll would probably only be 40 - 80 K or something like that. PowerBASIC generates real tight machine code. Actually, that's one of the major reasons I moved away from Microsoft application development technologies. Too many dependencies.
Last edited on
maybe because vb2008 runs on .NET frameworks
My build system do it by self.
I use scons. It's advanced build system.
http://www.scons.org
Thanks Freddie for the explanations and links... they helped us, although I think we can't buy this PowerBasic.

And thanks Denis for the link od SCons. It will be a valuable help for our project.

But comming back to the problem, I was trying to create the DLL myself and then read it in my C++ code using the "LoadLibrary" and "GetProcAddress" functions. This part I guess it is ok, but I've stucked in creating the DLL.

I've found this link that uses some windows command line statements in the example to create the dll.

http://www.stat.ubc.ca/~webmaste/howto/faq/windows/rlinkwin.html

I tried to do the same, but with the code in BASIC instead of C. I was able to compile the code (which I called MYFUNC.BAS) using QBasic but when I tried to execute the second command line (the first using 'dllwrap') I got the following:

C:\Documents and Settings\micro\Desktop\MyDll>dllwrap --export-all-symbols -o my
func.dll MYFUNC.OBJ
dllwrap: no export definition file provided.
Creating one, but that may not be what you want
MYFUNC.OBJ: file not recognized: File format not recognized
collect2: ld returned 1 exit status
dllwrap: gcc exited with status 1

C:\Documents and Settings\micro\Desktop\MyDll>dllwrap --export-all-symbols -o my
func.dll MYFUNC.EXE
dllwrap: no export definition file provided.
Creating one, but that may not be what you want
MYFUNC.EXE: file not recognized: File format not recognized
collect2: ld returned 1 exit status
dllwrap: gcc exited with status 1


Does anyone know how to use these commands to create the dll with the BASIC code? Any other suggestions?

Follows the codes I'm using:

MYFUNC.BAS:

1
2
3
4
5
DECLARE FUNCTION MyFunc! (a%, b%)

FUNCTION MyFunc (a%, b%)
       MyFunc = a% + b%
END FUNCTION



testDll.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <windows.h>
#include <stdio.h>
#include <iostream>

typedef UINT (CALLBACK* LPFNDLLFUNC1)(UINT,UINT);

using namespace std;

int main()
{
	HINSTANCE hDLL;               // Handle to DLL
	LPFNDLLFUNC1 lpfnDllFunc1;    // Function pointer
	UINT  uParam1, uParam2, uReturnVal;
	
	uParam1 = 22;
	uParam2 = 3;

	hDLL = LoadLibrary("myfunc.dll");
	if (hDLL != NULL)
	{
	   lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, "MyFunc");
	   if (!lpfnDllFunc1)
	   {
		  // handle the error
		  FreeLibrary(hDLL);
		  cout << "Error code: " << GetLastError() << "\n";
		  return -1;
	   }
	   else
	   {
		  // call the function
		  uReturnVal = lpfnDllFunc1(uParam1, uParam2);
		  cout << "Value: " << uReturnVal << "\n";
	   }
	}

	return 0;
}


Thanks again,

Leonel
Last edited on

I was able to compile the code (which I called MYFUNC.BAS) using QBasic but when I tried to execute the second command line (the first using 'dllwrap') I got the following:


Perhaps I'm wrong, and someone please correct me if I am, but I don't believe you are going to have much luck accessing code in a 16 bit dll even if you manage to create one. The other thing is, QBasic is an interpreter that runs pseudo code. Don't know how you are creating even an exe with that, not to even mention a dll. QuickBasic 4.5 or PDS 7.1 will generate 16 bit binary exes, but connecting them to 32 bit Windows exes would be a real trip! I think it might be possible to do it somehow through the ntvdm, but its way over my head.

Since you can't go the PowerBASIC route, my vote would still be with Visual Basic 6 and a regular dll.

In terms of the error messages above, they relate to the fact that whatever program you are using doesn't know what to export. If procedures in Dlls are to be visible and callable from programs that attempt to load them into their process, they need to be marked as exported. In C/C++ you do that be providing a module definition file (*.def ) or by using the ...

__declspec (dllexport)

attribute.
Something just occurred to me. Visual Basic 6 does not create standard Windows Dlls. It creates Active X (COM Objects) objects housed in a Dll. Big important difference! It could still be accessed through C++, but not quite as directly as LoadLibrary()/GetProcAddress() as with a standard dll. In that case it would need to be either registered as a COM object, or accessed as a non-registry entity through DllGetClassObject() then GetProcAddress(). Doable, but don't know if you are prepared for that.

First you said you built the program in Visual Studio 2008 then later you said it was built in Visual Basic 6. Now you're trying to compile basic code with some kind of 'R' compiler and I havn't a clue what that is, but it doesn't seem to be working.
Last edited on
Guys,

Thanks everyone for the help. I managed to partially solve my problem in the following way:

I created the following BAS file, with code in FreeBasic (that I found on the Internet)
1
2
3
4
5
DECLARE SUB TestInteger lib "DLL_test" alias "TestInteger" (byval myData AS Integer)

SUB TestInteger (byval myData AS Integer) EXPORT
    print "In FreeBasic your integer  = " , myData
END SUB


The C++ code is similar to the one I have already posted here...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <windows.h>
#include <stdio.h>
#include <iostream>

typedef VOID (CALLBACK* LPFNDLLFUNC1)(UINT);

using namespace std;

int main()
{
	HINSTANCE hDLL;               // Handle to DLL
	LPFNDLLFUNC1 lpfnDllFunc1;    // Function pointer
	UINT  uParam1;
	
	uParam1 = 32;

	hDLL = LoadLibrary("DLL_test.dll");
	if (hDLL != NULL)
	{
	   lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, "TestInteger@4");
	   if (!lpfnDllFunc1)
	   {
		  // handle the error
		  FreeLibrary(hDLL);
		  cout << "Error code: " << GetLastError() << "\n";
		  system("PAUSE");
		  return -1;
	   }
	   else
	   {
		  // call the function
		  lpfnDllFunc1(uParam1);
		  system("PAUSE");
	   }
	}
	
	FreeLibrary(hDLL);

	return 0;
}


I downloaded and installed the FreeBasic compiler (http://www.freebasic.net/index.php) and created a DLL from the Basic code using the following command

fbc -dll "c:\documents and settings\DLL_test.bas"


The dll was successfully created and I could sucessfully run my code in C++, giving me the output I wanted.

However, like I said, it didn't solve my problem entirely because the code I have to use in my C++ code is QBasic, not FreeBasic.

So, I converted the code in FreeBasic to QBasic, having as a result the following...
1
2
3
4
5
DECLARE SUB TestIntegerQB lib "DLL_test_QB" alias "TestIntegerQB" (myData%)

SUB TestIntegerQB (myData%)
    print "In QuickBasic your integer  = " , myData%
END SUB


I also changed what I needed in the C++ code (changed the name of the DLL to be loaded and the name of the function appropriately). I tried to generate the DLL with the QB code with the following command:

fbc -lang qb -dll "c:\documents and settings\DLL_test_QB.bas"


and got the following error
dlltool.exe: Syntax error in def file: C:\Documents and Settings\DLL_test_QB.def:0


The 'def' file is shown bellow:

1
2
3
LIBRARY DLL_test_QB
EXPORTS
	TestIntegerQB @1


Does anyone know why I received this error message?

Thanks in advance,

Leonel
Sounds to me like a FreeBasic question - not a C/C++ question. However, I believe DLL_test_QB needs to be in quotes, i.e., "DLL_test_QB".
I know it's not a C/C++ question, but you are already familiar with the problem... I'm posting this in FreeBasic forums also...

Anyway, putting DLL_test_QB between quotes as you suggested resulted in the same error message :(

Any other suggestions?
A guy in a FreeBasic forum helped me to solve the problem of creating the dll from the QB code.

I just needed to put the key word __export in the definition of the procedure TestIntegerQB as shown below.


1
2
3
SUB TestQB (myData%) __EXPORT
    print "In QuickBasic your integer  = " , myData%
END SUB



The 'def' file was correct.

Thanks everyone
Topic archived. No new replies allowed.