Author Topic: "Unable to find variable" when using external library on Linux  (Read 1194 times)

0 Members and 1 Guest are viewing this topic.

Offline JotEmI

  • Soldier
  • **
  • Posts: 188
I'm testing the new functionality of Soldat server - external libraries support.
I created a sample library with just one function that connects to MySQL server and retrieves one row based on a passed variable. Then I wrote a little test program to see if it would work and it did.

So I've put that library in soldatserver root directory and wrote a script that makes use of it but when server starts I get "Unable to find variable" error. Following http://devs.soldat.pl/wiki/index.php?title=Using_DLLs I exported LD_LIBRARY_PATH (export LD_LIBRARY_PATH=/path/to/soldatserver) but that didn't help either.

Here's the code of my library and .pas:

lib
Code: [Select]
#include <stdio.h>
#include "mysql.h"
#include <string>
#include <sstream>

std::string CheckAccount(std::string Name)
{
MYSQL_RES *result;
MYSQL_ROW row;
MYSQL *connection, mysql;
int state;
std::string w;
std::stringstream tmp;

w="";
mysql_init(&mysql);

connection=mysql_real_connect(&mysql,"host","user","pass","database",0,0,0);
if(connection==NULL)
{
return "";
}

state = mysql_query(connection, ("SELECT A,B FROM Table WHERE X='"+Name+"'").c_str());
if(state!=0)
{
return "";
}

result = mysql_store_result(connection);
while((row=mysql_fetch_row(result))!=NULL)
{
tmp << (row[0] ? row[0] : "NULL") << "_" << (row[1] ? row[1] : "NULL");
}

              w = tmp.str();

mysql_free_result(result);
mysql_close(connection);

return w;
}

pas
Code: [Select]
function Check(Name: string): string;
external 'CheckAccount@lib.so;

procedure OnJoinGame(ID, Team: byte);
var
dane: string;
begin
dane:=Check(GetPlayerStat(ID,'Name'));
WriteLn(dane);
end;

Offline SyavX

  • Soldat Beta Team
  • Camper
  • ******
  • Posts: 338
Re: "Unable to find variable" when using external library on Linux
« Reply #1 on: May 19, 2012, 09:12:16 am »
1st, read this:
Quote
[12-03-31 17:27] * Mr: SyavX: When sending strings around between Delphi and C, you need to do a bit of memory management yourself.
[12-03-31 17:28] * Mr: Here's what will not work:
[12-03-31 17:28] * Mr: Passing strings from the script core to an exported function taking std::string as argument
[12-03-31 17:28] * Mr: Using C strings from the script core after the script function returned - copy the string instead
[12-03-31 17:28] * Mr: Using the string type in the script core to pass something to a function that exports char* (it will mess with the reference counter)
[12-03-31 17:47] * Mr: SyavX: http://codepad.org/iL0EzIMJ
[12-03-31 17:48] * Mr: To make things easier when returning strings from C to Delphi/Pascal, you can copy the returned string into managed memory (string type in Delphi), free it afterwards and just continue using the string.

2nd, there is a typo (closing quotation mark):
Code: [Select]
external 'CheckAccount@lib.so;
P.S. Heh, I was going to release a Soldat DB lib (SQLite, PostgreSQL, ODBC) after 1.6.3 release,  but I had no time and enthusiasm to finish the examples code and documentation...

upd: libdb
« Last Edit: July 11, 2012, 01:22:10 pm by SyavX »

Offline JotEmI

  • Soldier
  • **
  • Posts: 188
Re: "Unable to find variable" when using external library on Linux
« Reply #2 on: May 19, 2012, 09:35:56 am »
Heh, I actually was afraid that there will be some problems with strings. Thx for clearing that out.

Offline CurryWurst

  • Camper
  • ***
  • Posts: 265
    • Soldat Global Account System
Re: "Unable to find variable" when using external library on Linux
« Reply #3 on: May 20, 2012, 08:29:31 am »
So I've put that library in soldatserver root directory and wrote a script that makes use of it but when server starts I get "Unable to find variable" error. Following http://devs.soldat.pl/wiki/index.php?title=Using_DLLs I exported LD_LIBRARY_PATH (export LD_LIBRARY_PATH=/path/to/soldatserver) but that didn't help either.

Make sure to compile 32-bit libraries if you run your compiler on a 64-bit operating system, since the Soldat server can only handle 32-bit binaries. In case you use a 64-bit version of the GNU Compiler Collection you can add the "-m32" flag to force 32-bit, i386 compatible output. You might need to install gcc-multilib with your favorite packet manager, if you haven't installed the appropriate multilib toolchain yet.
Soldat Global Account System: #soldat.sgas @ quakenet

Offline CurryWurst

  • Camper
  • ***
  • Posts: 265
    • Soldat Global Account System
Re: "Unable to find variable" when using external library on Linux
« Reply #4 on: May 20, 2012, 08:46:17 am »
Oh, and don't forget about name mangling if you deal with C++ compilers. To prevent name decoration of exported functions, you should resort to the extern "C" statement. You will find a pretty good article about how to export your code properly here. Even though the example provided in the article shows how to export an entire C++ class, I strongly do not recommend to export any C++ functions or classes due to C++'s instable Application Binary Interface (ABI). Hence, I suggest to stick to vanilla C functions.
« Last Edit: May 20, 2012, 02:32:57 pm by CurryWurst »
Soldat Global Account System: #soldat.sgas @ quakenet