Get string from dll

Blitz3D Forums/Blitz3D Programming/Get string from dll

Ferret(Posted 2005) [#1]
Hi,

Ive written some functions in c++ wich i can call from a .dll in Blitz.
How do i return a string from the c++ function to a blitz variable.

C++ code:
#include <iostream>
#include <fstream>
#include <windows.h>

using namespace std;

char acUserName[100];
DWORD nUserName = sizeof(acUserName);

__declspec( dllexport ) string getuser();
__declspec( dllexport ) int writeuser();
__declspec( dllexport ) int main();

int main()
{
	getuser();
	writeuser();
}

string getuser()
{
	GetUserNameA(acUserName, &nUserName);
	return acUserName;
	//return 0;
}

int writeuser()
{
	ofstream myfile;
	myfile.open ("user.txt");
	myfile << acUserName;
	myfile.close();
	return 0;
}


Blitz code:
result = CallDLL("GetUser","getuser")

Print "Result= " + result
WaitKey()

End



jfk EO-11110(Posted 2005) [#2]
I am not an expert, but since none answered so far, I try to help noneless.

One way that would work is: Blitz can tell the DLL a bank adress (absolute 32Bit). The DLL may then write the string to the bank, NULL terminated or whatever you like. Simply use RTLMemoryMove in the DLL. When you are using a Userlib to access the DLL, then you can use the banks handle from ithin Blitz and BLitz will send its adress. If you want to use the CallDLL method, you still can hack a banks absolute Data Adress, see COde Archives/userlibs/bankAsImage on how to obtain a banks absolute data segement adress.


BlackJumper(Posted 2005) [#3]
Here is a snippet from a dll that I coded in Borland C++ Builder...
//#define BBDECL extern "C" _declspec(dllexport)
//#define BBCALL _stdcall

//-------  Exported function ---------------------------------------------------
BBDECL const char* BBCALL GetStickyKeysVersionNumber()
{
   OSVERSIONINFO Ver;
   bool W98ME = false;
   Ver.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
   if ( GetVersionEx(&Ver) == true )
      {
         if ((Ver.dwMajorVersion == 4) && (Ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS))
           //  { if ( (Ver.dwMinorVersion == 10)||(Ver.dwMinorVersion == 90) )
            { W98ME = true;
            }           //}
      }
   if (W98ME == true)
      { return "Black Jumper Software Ltd. : Version 2.01  running W98 or ME";
      }
   else
      { return "Black Jumper Software Ltd. : Version 2.01 running on modern Win OS";
      }
}


Most of the code at the top is irrelevant. Notice that the return values are 'fixed strings' that I guess BC++ will convert internally to null-terminated strings.

The decls file has this in it...

.lib "StickyKey_dll.dll"
GetStickyKeysVersionNumber$()


... seems to do the job, but there might be differences if you are using a MS compiler or some other brand


seyhajin(Posted 2005) [#4]
Look the userlibs.txt :)

Example
-------

Ok, here's a little C++ example, as it would appear in VisualC.

First, we write the DLL:

//demo.dll
//
#include <math.h>
#include <string.h>
#include <stdlib.h>

#define BBDECL extern "C" _declspec(dllexport)
#define BBCALL _stdcall

//returns a float and has 6 float parameters
BBDECL float BBCALL VecDistance( float x1,float y1,float z1,float x2,float y2,float z2 ){
	float dx=x1-x2,dy=y1-y2,dz=z1-z2;
	return sqrtf( dx*dx+dy*dy+dz*dz );
}

//returns a string and has one string parameter
BBDECL const char * BBCALL ShuffleString( const char *str ){
	static char *_buf;

	int sz=strlen(str);

	delete[] _buf;
	_buf=new char[ sz+1 ];
	strcpy( _buf,str );
	
	for( int k=0;k<sz;++k ){
		int n=rand()%sz;
		int t=_buf[k];_buf[k]=_buf[n];_buf[n]=t;
	}

	return _buf;
}


After building this, the resultant 'demo.dll' should be placed in the userlibs directory.

Now, we also need to create a 'demo.decls' file, describing the functions in our dll. This file
is also placed in the userlibs directory:

.lib "demo.dll"
VecDistance#( x1#,y1#,z1#,x2#,y2#,z2# ):"_VecDistance@24"
ShuffleString$( str$ ):"_ShuffleString@4"


BlackJumper(Posted 2005) [#5]
I think the main thing to be wary of with most compilers is the 'Name-mangling' that occurs so that you need to add the version in quotes (as in Seyhajin's example)...

so VecDistance#(...) becomes "_VecDistance@24"

check your compiler's documentation for how to retrieve the mangled version from the compiled output.


Ferret(Posted 2005) [#6]
Thank you verry much for all the replys.

Right now i'm using a work around, write the string to a file and read it in Blitz, but thats not what i wanted.

I'm going to try this stuff out tomorow, to late to learn now :)


Ferret(Posted 2005) [#7]
It works right out of the box, now i can start experimenting with it :)

I did some research on name mangling and found a tool with source that displays the mangled names.
http://www.codeproject.com/debug/LibView.asp

Thx again for the help.