?
Solved

DLL plugin question

Posted on 2003-12-11
2
Medium Priority
?
736 Views
Last Modified: 2013-11-18
I'm developing DLL plugin system. Main application is written in Delphi. I'm having problem when I need to direct some variable to DLL, that will modify the variable content. Raw example:

main application runs ProcessPlugin procedure that will update some text variable, let's call it AData.

main application:

var AData: string;
begin
  AData := 'OldData'; // AData may contain some old data
   ProcessPlugin(AData);
   ShowMessage(AData);
end;

DLL plugin:

procedure ProcessPlugin(var AData: string);
begin
   AData := 'New Data';
end;

What is the better way to make this? I think there should be some tricks with pointers and memory allocations?

Alex
0
Comment
Question by:iam_dumb
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
2 Comments
 
LVL 26

Accepted Solution

by:
Russell Libby earned 500 total points
ID: 9925401

Alex,

When writing dlls, it is best to avoid the passing of Delphi strings, unless the caller (application) is ALWAYS going to be Delphi. And even when it is Delphi, you still need to include the ShareMem unit in BOTH the dll and the executables "uses" clause.

In many Windows API situations, where the dll modifies the contents of some "buffer" passed in to it, the caller passes a pointer to PChar/Block of memory, etc, as well as a flag indicating the max size of the buffer passed in. If the buffer is too small, the dll returns a status code indicating so (or GetLastError returns the error). In newer APIs, the size flag is passed "By reference" and modified to reflect the size of the data written/or size required.

Simple example:

function ProcessPlugin(lpszData: PChar; var dwSize: DWORD): Boolean;
var s: String;
begin

 s:='New Data';
 // Make sure buffer is large enough
 if dwSize > Succ(Length(s)) then
 begin
   // Copy string
   StrPCopy(lpszData, s)
  // Update the byref size variable to indicate the size of the result
   dwSize:=Length(s);
  // Success
   result:=true;
 end
 else
 begin
   // Update the size variable to notify the caller how large a buffer is needed
   dwSize:=Succ(Length(s));
  // Failure
   result:=False;
 end;
end;

Caller Code:

var
 p:           PChar;
 dwSize:  DWORD;
begin

 dwSize:=100;
 p:=AllocMem(dwSize);

 if not(ProcessPlugin(p, dwSize)) then
 begin
   FreeMem(p);
   p:=AllocMem(dwSize);
   ProcessPlugin(p, dwSize);
 end;

end;

There may also be times (maybe your situation), where the dll may need a very large buffer to write the return results, and it is not feasible for the application to allocate this much memory blindly. If this is the case, then you could have the dll/exe use standard heap functions, like HeapAlloc, HeapFree, etc or GlobalAlloc, GlobalLock, GlobalFree, etc. The the caller would just pass in a var Pointer, the dll would allocate required memory via the function, and when the app is done, it could call the associated free function (HeapFree/GlobalFree). This would allow apps written in other languages to utilize your dll as well

Hope this helps (and makes sense),
Russell







0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 9925463

Sorry, small typo on my part...

Example code

 // Make sure buffer is large enough
 if dwSize > Succ(Length(s)) then
 begin
    ....

should be:

 if dwSize >= Succ(Length(s)) then
 begin
    ....

Also, as another note; by reference (var) Variant passing is also another viable option, where the string can be set with StringToOleStr, and retrieved with OleStrToString. Once the application clears the variant (variant = unassigned) the memory is freed for you. Under the covers,  CoTaskMemAlloc / CoTaskMemFree / SysAllocString / etc, all get handled for you.

Regards,
Russell

0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
The purpose of this video is to demonstrate how to set up the WordPress backend so that each page automatically generates a Mailchimp signup form in the sidebar. This will be demonstrated using a Windows 8 PC. Tools Used are Photoshop, Awesome…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
Suggested Courses
Course of the Month12 days, 8 hours left to enroll

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question