#1 2011-11-18 10:27:03

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Framework in a DLL

Hi,

I'm working on an Delphi project that use the mORMot Framework. I have a client/server application that work on a LAN but I think you just know it smile.

I want add advanced options to import and export data from databasefrom/to many types of files. I'd like create 2 DLL for these reason to not add many code to my application.

I only developed a library until now, so I'd like to know the opinion of the administrator.

The user can import/export data only from/to the opening database and I think I have 2 altervatives:

1) I can pass my database object (TSQLRestClientURI) from application to DLL: I don't know if this way works but if it works I can import/export data from any computer of my LAN. I have read of memory problem with DLL if I use object.

2) I can pass only database filename, then open this database from DLL and import/export data. In this way I open the some database both on application and DLL and I don't know if it is a good idea. Besides in this way I can use import/export data only from server application (not from client application).

I think the 1) is the best solution for me but I don't know if is possible. What do you think about it? Is possible pass the database object from application to DLL, make import/export function than close DLL without problem?

If you have other ideas, these are welcome.

Offline

#2 2011-11-18 10:37:23

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Framework in a DLL

You can use the TSQLRestClientURIDll class.
This does exactly what you need.

The main application can pass a TURIMapRequest instance to the library.

Online

#3 2011-11-18 13:02:53

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Framework in a DLL

I love most every day this framework. Is there a small example about it? Can you add a small demo to your framework demos?
I'have tried to load the documentation without success, I don't have write many DLL untiln now.

Offline

#4 2011-11-28 13:54:00

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Framework in a DLL

I have read the documentation to try to create my DLL.

1) In my DLL I will use TSQLRestClientURIDll to connect with my database (the database is open inside the application);
2) To create TSQLRestClientURIDll inside the DLL I need pass as parameter the TURIMapRequest object from my application to my DLL, this object. In fact I need use TSQLRestClientURIDll.Create(aModel: TSQLModel; aRequest: TURIMapRequest);

However I don't have understand how I can create TURIMapRequest from my server. In your documentation I see this:

TURIMapRequest = function(url, method, SendData: PUTF8Char; Resp, Head: PPUTF8Char): Int64Rec; cdecl;

But in practice how can I create this object? With such parameters?

Offline

#5 2011-11-28 14:49:06

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Framework in a DLL

Create a global function like this:

function MyUrlMapRequest(url, method, SendData: PUTF8Char; Resp, Head: PPUTF8Char): Int64Rec; cdecl;
begin
  .... implement here
end;

In fact, this is not a class method, but a plain global function.

Online

#6 2011-11-28 14:57:56

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Framework in a DLL

OK, so this function is use inside the application to "execute" the request by the TSQLRestClientURIDll object inside the DLL, right?

and what I need implement in this function? For example my dll must import some new record inside a table of my database.

Offline

#7 2011-11-28 15:03:04

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Framework in a DLL

You have already a typical implementation of this function in SQLite3Commons.pas.

You only need to:
- Set a TSQLRestServer instance to the GlobalURIRequestServer variable - this can be done directly by calling the TSQLRestServer.ExportServer method;
- Use URIRequest global function, which maps TURIMapRequest prototype.

See:

/// this function can be exported from a DLL to remotely access to a TSQLRestServer
// - use TSQLRestServer.ExportServer to assign a server to this function
// - return 501 NOT IMPLEMENTED error if no TSQLRestServer.ExportServer has been assigned
// - memory for Resp and Head are allocated with GlobalAlloc(): client must release
// this pointers with GlobalFree() after having retrieved their content
// - simply use TSQLRestClientURIDll to access to an exported URIRequest() function
function URIRequest(url, method, SendData: PUTF8Char; Resp, Head: PPUTF8Char): Int64Rec; cdecl;

If you define USEFASTMM4ALLOC = true, it will use FastMM4 instead of slower GlobalAlloc/GlobalFree.
But the FastMM4 instance must be shared between the main process and the library.

Online

#8 2011-11-28 23:22:47

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Framework in a DLL

Until now I have understand:

1) On my application I must call TSQLRestServer.ExportServer to set GlobalURIRequestServer;
2) On my dll I must TSQLRestClientURIDll as client, however TSQLRestClientURIDll have 2 Create function and I think I must use Create(aModel: TSQLModel; aRequest: TURIMapRequest); because my database is on my application.

I don't understand this TURIMapRequest, you say "Use URIRequest global function, which maps TURIMapRequest prototype.". I must use the function URIRequest as aRequest parameter? What maen your post #5?

Offline

#9 2011-11-29 07:56:21

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Framework in a DLL

As stated by the URIRequest function comment:

simply use TSQLRestClientURIDll to access to an exported URIRequest() function

Online

#10 2011-11-29 21:59:30

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Framework in a DLL

OK, I have make some test.

On my application I call my DLL function with this code:

var
  fHND: THandle;
  DLLTestExetute: TDLLTestExetute;
begin
  if FileExists(AppPath + 'cltest.dll') then
    begin
      DatabaseServer.ExportServer;

      fHND := LoadLibrary(pChar(AppPath + 'cltest.dll'));

      try
        if fHND <> 0 then
          begin
            @DLLTestExetute := getProcAddress(fHND, 'DLLExecute');

            DLLTestExetute();
          end
        else
          begin
            // MSG DLL NOT LOAD
          end;
      finally
        if fHND <> 0 then
          FreeLibrary(fHND);
      end;
    end
  else
    begin
      // MSG DLL NOT FOUND
    end;

this is my dll code:

procedure DLLExecute();
var
  client: TSQLRestClientURIDll;
  test: TSQLTableJSON;
begin
  client := TSQLRestClientURIDll.Create(GetDatabaseModel(), URIRequest);

  MessageDlg('TableRowCount: ' + IntToStr(client.TableRowCount(TSQLProjects)),  mtConfirmation, [mbOK], 0);

  if client <> nil then
    begin
      test := client.ExecuteList([], 'SELECT COUNT(*) FROM Projects');

      if test <> nil then
        begin
          try
            if test.RowCount > 0 then
              begin
                MessageDlg('Record number: ' + IntToStr(test.RowCount),  mtConfirmation, [mbOK], 0);
              end
            else
              begin
                MessageDlg('NO ROWS',  mtConfirmation, [mbOK], 0);
              end;
          finally
            test.Free;
          end;
        end
      else
        begin
          MessageDlg('TEST NIL',  mtConfirmation, [mbOK], 0);
        end;

      client.Free;
    end
  else
    begin
      MessageDlg('CLIENT NIL',  mtConfirmation, [mbOK], 0);
    end;
end;

exports
  DLLExecute;

this code doesn't work, client.TableRowCount(TSQLProjects) = -1 but the Project table have 5 records besides TEST is nil.

So I think there are some errors on my code.

Any suggestions?

Offline

#11 2011-11-30 10:11:08

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Framework in a DLL

Did you use the debugger to step into the request?

Since it will run in-process, you can step into the server directly.

It will certainly let you discover what fails.

Online

#12 2011-11-30 10:26:22

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Framework in a DLL

But the code is corret? I have debugger the application without success.

Offline

#13 2011-11-30 10:29:19

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Framework in a DLL

Where is the server-side process stopped?

Steps into TSQLRestServer.URI method.

Online

#14 2011-11-30 17:54:06

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Framework in a DLL

From my test when I use my code to call dll function (post #10) don't call TSQLRestServer.URI. So I think there is a error on my code but I don't understand where.

Offline

#15 2011-11-30 18:56:26

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Framework in a DLL

From your code, I suspect you're doing the contrary of the dll implementation pattern.

The server should be inside the dll, and the client an external exe.

Online

#16 2011-11-30 22:14:57

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Framework in a DLL

OK but I need the server on the application and the client on DLL. The dll is only a plugin of my application to import data into database from few file format (csv, xml, ...).

This is my idea: I have I server application and more client application, the server application can use the dll (as another client) to import the data into the database.

Is it possible?

On your framework I can use the DLL only as server? or there a solution for me

Offline

#17 2011-12-01 14:41:51

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Framework in a DLL

array81 wrote:

On your framework I can use the DLL only as server? or there a solution for me

You can do that, of course.

But you'll have to reverse the function use, and provide some external functions exported from the DLL to start and stop the server.
When starting the server, you can return a pointer to the may URIRequest function to be called from your main executable.

Online

#18 2011-12-01 15:24:22

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Framework in a DLL

There is something you still do not understand.

On application (for me the server) I use:

DatabaseServer.ExportServer;

then call the DLLExecute function to execute the code inside the dll, in my application I use:

client := TSQLRestClientURIDll.Create(GetDatabaseModel(), URIRequest);

to create my client and import the data inside the database, what are these functions that I need invert?

Offline

#19 2011-12-01 16:20:31

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: Framework in a DLL

You have to specify the Server URIRequest() pointer to the Client library, e.g. by setting a parameter to the DllExecute exported function.

Online

Board footer

Powered by FluxBB