1. DLL Interface
- Posted by cp Nov 06, 2008
- 1009 views
I have a need to interface with a DLL that talks to a database server. There are two versions of the DLL a 'C' version and a 'VB' version.
I have a requirement to send strings to and return strings from the DLL. The function header (C version of API)for returning the string is defined as: DB1IMPORT CHAR * DB1API DB1ValStringGet( DB1U hUser, DB1V vString );
The VB version returns a VB string and is defined as: Declare Sub DB1ValStringGet_VB Lib "db1api.dll" (ByVal hUser As Long, ByVal vString As Long, ByVal res As String, ByVal max As Integer)
What is the best way for me to get/receive strings (char arrays) from this api keeping in mind that the database and Eu program will not be on the same machine.
2. Re: DLL Interface
- Posted by scooby Nov 06, 2008
- 968 views
You could use either version of the dll. The VB version is alot simpler to implement but may not offer the full functionality of the API.
For any dll, you need to import the code you need to use into euphoria.
First, you must open the required dll and store it's handle.
constant DLL = open_dll("db1api.dll")
then for each function you want to import, you will have to define it for euphoria
-- Declare Sub DB1ValStringGet_VB Lib "db1api.dll" (ByVal hUser As Long, ByVal vString As Long, ByVal res As String, ByVal max As Integer) constant C_DB1ValStringGet = define_c_proc(DLL,"DB1ValStringGet_VB",{C_LONG,C_LONG,C_POINTER,C_UINT})
Notice above that the defined variable C_POINTER corresponds with ByVal res as String. It's actually the memory address of the string that is passed, not the chars themselves.
C strings are terminated with a byte value of 0, so to read the string, you peek each byte starting from the string's address until you encounter a value of 0. (which is what peek_string() does in the code below)
For ease of use, you should also define a wrapper function, this is where you will handle converting char arrays to euphoria sequences and simplify the use of the API function in eu.
function DB1ValStringGet(atom hUser, atom vString) atom buffer integer MAX_LEN sequence s MAX_LEN = 255 buffer = allocate(MAX_LEN) c_proc(C_DB1ValStringGet,{hUser,vString,buffer,MAX_LEN}) s = peek_string(buffer) deallocate(buffer) return s end function
I don't think that peek_string() is in the standard libraries, so here it is in case you need it. The optimized version is not very clear what it does, so I've provided a slow version as well.
-- unoptimized function slow_peek_string(atom ptr) sequence s integer c c = peek(ptr) while (c != 0) do s &= c end while return s end function -- optimized function peek_string(atom ptr) integer len len = 0 while (peek(ptr+len) != 0) do len += 1 end while return peek({ptr,len)) end function
You can read more about interfacing with C in platform.doc
HTH
3. Re: DLL Interface
- Posted by scooby Nov 06, 2008
- 969 views
I made a mistake in slow_peek_string() it should be:
function slow_peek_string(atom ptr) sequence s integer c c = peek(ptr) while (c != 0) do s &= c ptr += 1 c = peek(ptr) end while return s end function
4. Re: DLL Interface
- Posted by cp Nov 06, 2008
- 1027 views
- Last edited Nov 07, 2008
Excellent explanation thanks very much.
One question I have is will Peek() to directly access memory location work if the DB is running on a different machine than the euphoria program?
If not is there a possible work around.
Thanks
5. Re: DLL Interface
- Posted by m_sabal Nov 07, 2008
- 1005 views
Yes it will. The DLL is actually sending a query to the remote database, and getting the answer back. The answer is in memory on your local machine, so peek will work just fine.
6. Re: DLL Interface
- Posted by SDPringle Nov 17, 2008
- 905 views
In general, it may be faster to just use the limit value, 255 in this case, as the argument to peek(). Then use find() to determine where truncate the sequence:
sequence s integer len atom ptr ptr = allocate( 256 ) -- C call using string in ptr goes here. s = peek( { ptr, 256 } ) free(ptr) len = find(0,s) if len then s = s[1..len-1] else return GET_FAIL -- too long error... end if return s
The length of the buffer is always known by the coder and in some cases the length of the string is returned by the underlying C function. Not all C functions terminate the string. We shouldn't assume that the requested string is limited to 255 characters. It is better to fail with an error than to crash the program.
Shawn Pringle