Recent

Author Topic: Help me with create .dll and .so  (Read 21245 times)

xinyiman

  • Hero Member
  • *****
  • Posts: 2256
    • Lazarus and Free Pascal italian community
Re: Help me with create .dll and .so
« Reply #15 on: June 25, 2010, 06:27:41 am »
Ok we are almost, I have to finish some things, but I got the list of odbc and tables!
The only thing that goes wrong when I use:
var:
    appoggio: PChar;

LiberaStringa(appoggio);

declared as follows:
procedure LiberaStringa (var val: PChar);cppdecl; external {$ifdef windows} 'ProgettoDLLODBC.dll'{$endif};


and the dll is:
EXTERN_C __declspec(dllexport) VOID LiberaStringa(char * val)
{
    delete(val);   
}


Why?
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

Whiterawen

  • New Member
  • *
  • Posts: 12
    • Lirein's Homepage
Re: Help me with create .dll and .so
« Reply #16 on: June 25, 2010, 07:38:34 am »
Of course, your call of "procedure LiberaStringa (var val: PChar);" looks as "void LiberiaStringa(char **val)" not as  "void LiberiaStringa(char *val)". Please, remember that PChar are already a pointer type declared as PChar=^Char; and declaration as var variable:type in procedure parameter always looks as a pointer to this variable.

Ahh, yes! Never do this:
EXTERN_C __declspec(dllexport) VOID GetDSNNum (INT num , CHAR * Dsn,CHAR * Desc)
{   
    PtrListaODBC * MiaLista;
    PtrListaODBC * app;
    int ret, i;
   
    MiaLista=RecuperaListaODBC();   
   app=MiaLista;
   i=0;
   while(app)
   {
      //printf("%s - %s\n", app->dsn, app->desc);
     
      if (i==num)
      {
            Dsn=(char*)malloc(sizeof(char)*strlen(app->dsn));
            sprintf(Dsn,app->dsn);   
            Desc=(char*)malloc(sizeof(char)*strlen(app->desc));
            sprintf(Desc,app->desc);           
        }
      i++;
      app=app->next;
   }
    CancellaListaODBC(MiaLista);
}

You assigns new pointer to a Dsn parameter, but it has pointer to first byte of string, that's whay you cant receive valid string both in C++ and Pascal, you can do two things:
One way is to pass Dsn as char* and length (uint32_t) of this buffer, and then assign value vith help of memcpy function.
Another way is to declare Dsn as char** and assign new value as code below:
            *Dsn=(char*)malloc(strlen(app->dsn)+1); //size of char data type is always equal to one byte (uint8_t) and we need a leading zero!
            sprintf(*Dsn,app->dsn);
            *Dsn[strlen(app->dsn)]=0; //add leading zero!

Because that you code may looks as:
EXTERN_C __declspec(dllexport) void MyCoolProc(char **MyVal) {
*MyVal=(char*)malloc(64);
strcpy(*MyVal,"Wow!!! It Works"); //strcpy already set leading zero
}

Procedure MyCoolProc(var MyVal:PChar); cppdecl; external;
« Last Edit: June 25, 2010, 08:01:29 am by Whiterawen »
WBR, Vanya Batalin.

xinyiman

  • Hero Member
  • *****
  • Posts: 2256
    • Lazarus and Free Pascal italian community
Re: Help me with create .dll and .so
« Reply #17 on: June 27, 2010, 09:48:49 pm »
I tried to be so

EXTERN_C __declspec(dllexport) VOID LiberaStringa(char ** val)
{
    free(*val);   
}


so that

EXTERN_C __declspec(dllexport) VOID LiberaStringa(char ** val)
{
    free(val);   
}


but in both cases, crashes in the first tells me appears to debug in assembler and the second one I did not return any error type but appears to debug in assembler. Why?  :o
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

xinyiman

  • Hero Member
  • *****
  • Posts: 2256
    • Lazarus and Free Pascal italian community
Re: Help me with create .dll and .so
« Reply #18 on: June 27, 2010, 10:09:11 pm »
To address this

http://www.freepascal.org/docs-html/ref/refsu13.html


says PChar is a pointer to a NULL terminated string. So I do not understand the intervention of Whiterawen that says it is a pointer to a pointer to a caratterre. Whiterawen you explain better? Thanks
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

Leledumbo

  • Hero Member
  • *****
  • Posts: 8744
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Help me with create .dll and .so
« Reply #19 on: June 29, 2010, 04:20:27 am »
He's trying to say that these two are equal:
Code: [Select]
procedure p1(var p: pchar);

procedure p2(p: ^pchar);
so a var parameter is the same as if you're passing a pointer, so those two above would equal in C as:
Code: [Select]
void p1(char** p); // or p2, no problem, both are the same

xinyiman

  • Hero Member
  • *****
  • Posts: 2256
    • Lazarus and Free Pascal italian community
Re: Help me with create .dll and .so
« Reply #20 on: June 29, 2010, 04:42:56 am »
Ok, but even with this information does not change the result. I go into the same error! On a trivial operation as a free area of memory allocated with malloc! Absurd
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1927
Re: Help me with create .dll and .so
« Reply #21 on: June 29, 2010, 04:59:16 am »
Have you tried using cdecl or stdcall instead of cppdecl ?

xinyiman

  • Hero Member
  • *****
  • Posts: 2256
    • Lazarus and Free Pascal italian community
Re: Help me with create .dll and .so
« Reply #22 on: June 29, 2010, 05:05:44 am »
Have you tried using cdecl or stdcall instead of cppdecl ?

My lazarus source

unit Unit1;

{$mode objfpc}{$H+}
{$ifdef unix}
{$linklib myfunc}
{$endif}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  ExtCtrls, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

  PtrListaODBC=^appoggio;
   Appoggio = record
   dsn : array[0..255] of char;
   desc : array[0..255] of char;
   next: PtrListaODBC;
  end;

var
  Form1: TForm1;

//function GetListaDSN(MiaLista: PtrListaODBC): PChar; cdecl; external {$ifdef windows} 'ProgettoDLLODBC.dll'{$endif};
function MaxDSN(): integer;cppdecl; external {$ifdef windows} 'ProgettoDLLODBC.dll'{$endif};
function GetDSN (num: integer): PChar;cppdecl; external {$ifdef windows} 'ProgettoDLLODBC.dll'{$endif};
function GetDescDSN (num: integer): PChar;cppdecl; external {$ifdef windows} 'ProgettoDLLODBC.dll'{$endif};
procedure LiberaStringa (var val: PChar);cppdecl; external {$ifdef windows} 'ProgettoDLLODBC.dll'{$endif};
function MaxTabelle(Dsn: PChar; Uid: PChar; Pwd: PChar): integer;cppdecl; external {$ifdef windows} 'ProgettoDLLODBC.dll'{$endif};
function GetNomeTabella(Dsn: PChar; Uid: PChar; Pwd: PChar; num: integer): PChar;cppdecl; external {$ifdef windows} 'ProgettoDLLODBC.dll'{$endif};
implementation

{ TForm1 }


procedure TForm1.Button1Click(Sender: TObject);
var
   app: PtrListaODBC;
   i: integer;
   MioDsn: Pchar;
   MiaDesc: PChar;
   MiaTab: PChar;
begin
 i:=0;
 for i:=1 to MaxDSN() do
 begin
   MioDSN:=GetDSN(i);
   MiaDesc:=GetDescDSN(i);
   ShowMessage(IntToStr(i) + '   ' + MioDSN + '   [' + MiaDesc + ']');
   LiberaStringa(MioDSN);
   LiberaStringa(MiaDesc);
 end;
 for i:=1 to MaxTabelle('MySql_Locale','mycinema','mycinema') do
 begin
   MiaTab:=GetNomeTabella('MySql_Locale','mycinema','mycinema',i);
   ShowMessage(IntToStr(i) + '   ' + MiaTab);
 end;


end;

initialization
  {$I unit1.lrs}

end.
                                 

My DEV CPP dll source

#include <windows.h>
#include <stdio.h>
#include "MyODBCLib.h"

EXTERN_C __declspec(dllexport) INT MaxDSN ();
EXTERN_C __declspec(dllexport) INT MaxTabelle (char * Dsn, char * Uid, char * Pwd);
EXTERN_C __declspec(dllexport) VOID GetDSNNum (INT num , CHAR * Dsn,CHAR * Desc);
EXTERN_C __declspec(dllexport) char * GetDSN (INT num);
EXTERN_C __declspec(dllexport) VOID LiberaStringa(char ** val);
EXTERN_C __declspec(dllexport) char * GetNomeTabella (char * Dsn, char * Uid, char * Pwd, INT num);

BOOL WINAPI __declspec(dllexport) LibMain (HINSTANCE hInst, DWORD Reason, LPVOID Reserved)
{
  if(Reason==DLL_PROCESS_ATTACH)
   {
     return   TRUE;
     }

  if(Reason==DLL_PROCESS_DETACH)
     {
     return   TRUE;
     }

  return   FALSE;
}


EXTERN_C __declspec(dllexport) INT MaxDSN ()
{
    PtrListaODBC * MiaLista;
    PtrListaODBC * app;
    int ret;
    MiaLista=RecuperaListaODBC();
    app=MiaLista;
    ret=0;
    while(app)
   {
      ret++;
      app=app->next;
   }
    CancellaListaODBC(MiaLista);
    return ret;
}

EXTERN_C __declspec(dllexport) INT MaxTabelle (char * Dsn, char * Uid, char * Pwd)
{
   PtrDatiODBC * MieiDati; //contiene i dati per collegarsi al oDBC
   PtrListaTabelle * MieTabelle;
   PtrListaTabelle * app;      
   char * strconn;
    int ret;
   
    strconn=(char*)malloc(sizeof(char)*(1+strlen(Dsn)+strlen(Uid)+strlen(Pwd)+strlen("DSN=;UID=;PWD=;")));
    strcpy(strconn,"DSN=");
    strcat(strconn,Dsn);
    strcat(strconn,";UID=");   
    strcat(strconn,Uid);   
    strcat(strconn,";PWD=");
    strcat(strconn,Pwd);   
    strcat(strconn,";");
   
    //MieiDati=ApriConnessioneODBC((SQLCHAR*)"DSN=MySql_Locale;UID=mycinema;PWD=mycinema;");
    MieiDati=ApriConnessioneODBC((SQLCHAR*)strconn);
    free(strconn);
   MieTabelle=RecuperaListaTabelle(MieiDati);
   
   app=MieTabelle;
   ret=0;
   while(app)
   {
      //printf("%s - %s\n", app->dsn, app->desc);      
      ret++;
      app=app->next;
   }         
   CancellaListaTabelle(MieTabelle);
    DisconnettiODBC(MieiDati); //mi disconnetto   
    return ret;
}


EXTERN_C __declspec(dllexport) VOID GetDSNNum (INT num , char * Dsn, char * Desc)
{   
    PtrListaODBC * MiaLista;
    PtrListaODBC * app;
    int ret, i;
    char * val1, *val2;
   
    MiaLista=RecuperaListaODBC();   
   app=MiaLista;
   i=0;
   while(app)
   {
      //printf("%s - %s\n", app->dsn, app->desc);
      i++;
      if (i==num)
      {
            val1=(char*)malloc(sizeof(char)*strlen(app->dsn));
            strcpy(val1,app->dsn);   
            val2=(char*)malloc(sizeof(char)*strlen(app->desc));
            strcpy(val2,app->desc);           
            Dsn=val1;
            Desc=val2;
        }      
      app=app->next;
   }
    CancellaListaODBC(MiaLista);
}

EXTERN_C __declspec(dllexport) char * GetDSN (INT num)
{   
    PtrListaODBC * MiaLista;
    PtrListaODBC * app;
    char * ret;
    int i;
   
    MiaLista=RecuperaListaODBC();   
   app=MiaLista;
   i=0;
   while(app)
   {
      //printf("%s - %s\n", app->dsn, app->desc);
      i++;      
      if (i==num)
      {
            ret=(char*)malloc(sizeof(char)*strlen(app->dsn));
            strcpy(ret,app->dsn);                   
        }
      app=app->next;
   }
    CancellaListaODBC(MiaLista);
    return ret;
}

EXTERN_C __declspec(dllexport) char * GetDescDSN (INT num)
{   
    PtrListaODBC * MiaLista;
    PtrListaODBC * app;
    char * ret;
    int i;
   
    MiaLista=RecuperaListaODBC();   
   app=MiaLista;
   i=0;
   while(app)
   {
      //printf("%s - %s\n", app->dsn, app->desc);
      i++;      
      if (i==num)
      {
            ret=(char*)malloc(sizeof(char)*strlen(app->desc));
            strcpy(ret,app->desc);   
        }
      app=app->next;
   }
    CancellaListaODBC(MiaLista);
    return ret;
}

EXTERN_C __declspec(dllexport) char * GetNomeTabella (char * Dsn, char * Uid, char * Pwd, INT num)
{
   PtrDatiODBC * MieiDati; //contiene i dati per collegarsi al oDBC
   PtrListaTabelle * MieTabelle;
   PtrListaTabelle * app;      
   char * strconn;
   int i;
    char * ret;
   
    strconn=(char*)malloc(sizeof(char)*(1+strlen(Dsn)+strlen(Uid)+strlen(Pwd)+strlen("DSN=;UID=;PWD=;")));
    strcpy(strconn,"DSN=");
    strcat(strconn,Dsn);
    strcat(strconn,";UID=");   
    strcat(strconn,Uid);   
    strcat(strconn,";PWD=");
    strcat(strconn,Pwd);   
    strcat(strconn,";");
   
    //MieiDati=ApriConnessioneODBC((SQLCHAR*)"DSN=MySql_Locale;UID=mycinema;PWD=mycinema;");
    MieiDati=ApriConnessioneODBC((SQLCHAR*)strconn);
    free(strconn);
   MieTabelle=RecuperaListaTabelle(MieiDati);
   
   app=MieTabelle;
   ret=NULL;
   i=0;
   while(app)
   {
      //printf("%s - %s\n", app->dsn, app->desc);      
      i++;
      if (i==num)
      {
            ret=(char*)malloc(sizeof(char)*strlen(app->nome));
            strcpy(ret,app->nome);   
        }
      app=app->next;
   }         
   CancellaListaTabelle(MieTabelle);
    DisconnettiODBC(MieiDati); //mi disconnetto   
    return ret;
}

EXTERN_C __declspec(dllexport) VOID LiberaStringa(char ** val)
{
    free(val);
}

If I comment a free function the program not return a sigsev error.
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4458
  • I like bugs.
Re: Help me with create .dll and .so
« Reply #23 on: June 29, 2010, 05:08:00 am »
@xinyiman: You clearly have problems with pointer syntax, like many other people have.

A question: why do you want to create a DLL with C and then use it from Object Pascal?
I understand if someone wants to use an existing DLL but you are making it yourself.

Do you feel there is something you can do with C that you cannot do with Object Pascal? Please tell what it is and someone may be able to help you.

Juha
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

xinyiman

  • Hero Member
  • *****
  • Posts: 2256
    • Lazarus and Free Pascal italian community
Re: Help me with create .dll and .so
« Reply #24 on: June 29, 2010, 05:15:07 am »
So I am not able to find a method crossplatform (win, linux) to get the odbc dsn and related information. Plus I could not get the name of tables with GetTableName (). So I decided to make a dll in C library with my work because I know I've worked on both Linux and Windows to obtain this information. If someone can tell me how to get it again without errors in a cross-platform then me suggest that I avoid creating a dll. Thanks
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4458
  • I like bugs.
Re: Help me with create .dll and .so
« Reply #25 on: June 29, 2010, 06:00:36 am »
So I am not able to find a method crossplatform (win, linux) to get the odbc dsn and related information.

ODBC is basically Windows only, although there are some Linux libs and other hacks made for it.

If you really want to make a crossplatform application, why would you want to use ODBC?

Juha
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

xinyiman

  • Hero Member
  • *****
  • Posts: 2256
    • Lazarus and Free Pascal italian community
Re: Help me with create .dll and .so
« Reply #26 on: June 29, 2010, 06:19:04 am »
So I am not able to find a method crossplatform (win, linux) to get the odbc dsn and related information.

ODBC is basically Windows only, although there are some Linux libs and other hacks made for it.

If you really want to make a crossplatform application, why would you want to use ODBC?

Juha

Exist on linux and unix-odbc work quite well. So I would not say that there are only on windows.
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4458
  • I like bugs.
Re: Help me with create .dll and .so
« Reply #27 on: June 29, 2010, 08:17:01 am »
Exist on linux and unix-odbc work quite well. So I would not say that there are only on windows.

At least it doesn't work well with FPC as you have noticed. If you make a crossplatform DB application using FPC / Lazarus there are much better alternatives than ODBC.

Juha
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

xinyiman

  • Hero Member
  • *****
  • Posts: 2256
    • Lazarus and Free Pascal italian community
Re: Help me with create .dll and .so
« Reply #28 on: June 29, 2010, 09:53:22 pm »
Really works very well, but I can not retrieve the DSN (on linux) and tables (on windows). I suggest some other option for cross-platform
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4458
  • I like bugs.
Re: Help me with create .dll and .so
« Reply #29 on: June 29, 2010, 11:22:32 pm »
Quote
Really works very well, but I can not retrieve the DSN (on linux) and tables (on windows).

It means it does not work very well. :-)
Cross platform ODBC seems to be supported by Lazarus, I didn't even know:
  http://wiki.lazarus.freepascal.org/ODBCConn

If you still want to use ODBC, you should report / fix bugs for it. A self made DLL coded with C doesn't sound like a good idea.
Anyway, I still recommend to use some other DB connection method for crossplatform.

Firebird and SQLite are crossplatform DBs, commonly used with FPC. There is a Lazarus builtin connection and there is ZEOSlib.

  http://wiki.lazarus.freepascal.org/Databases
  http://wiki.lazarus.freepascal.org/Lazarus_DB_Faq

You could read messages and maybe ask further questions here :
  Forum > Programming > Databases

Juha
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

 

TinyPortal © 2005-2018