Solved

DLL plugin question

Posted on 2003-12-11
2
729 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
Comment Utility

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
Comment Utility

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

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

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…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
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…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

772 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

11 Experts available now in Live!

Get 1:1 Help Now