Solved

DLL plugin question

Posted on 2003-12-11
2
731 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
  • 2
2 Comments
 
LVL 26

Accepted Solution

by:
Russell Libby earned 125 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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Simple Delphi Question 9 83
Internet Explorer View Settings Question 15 106
Search on a site 5 95
Can Viruses spread while transferring Binary data with Winsock 2 66
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Before we dive into the marketing strategies involved with creating an effective homepage, it’s crucial that EE members know what a homepage is. In essence, a homepage is the introductory, or default page, of a website that typically highlights the …
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…
With the power of JIRA, there's an unlimited number of ways you can customize it, use it and benefit from it. With that in mind, there's bound to be things that I wasn't able to cover in this course. With this summary we'll look at some places to go…

895 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now