tags:

views:

162

answers:

3

After this question, I need to know what principles should be followed in order to make an encapsulation of a class in a dll compatible to other version of Delphi. I made a class using generics feature in RAD2010 and make a dll which has a function that return an instance of it. When I tried to use the dll using BDS2006 or Delphi 6, the DLL didn't work as expected. But if I use RAD2010 in other computer, there is no issue. Is it caused by using the feature that not available in previous Delphi version (the stack<> stuffs?)? For string matters, I already follow the comment guidance in the library file, that I put ShareMem in both library first uses clause and my project. And I have copied borlndmm.dll from RAD2010 to the same folder where I tried the DLL using BDS2006. It didn't crash, but it didn't work es expected. A function return an empty string when in RAD2010 environment it worked very well.

Once again, I have a question : what principles should be followed in order to make an encapsulation of a class in a dll compatible to other version of Delphi? Thank you in advance. (For encapsulating functions in a dll when no OOP is used, I have no issued for other version of Delphi).

+8  A: 

The definition of a string changed with D2009. If you want to make string communication safe, use a PAnsiChar or a WideString.

The basic rule of communication through DLLs is to not use anything specific to Delphi, so no Delphi strings and no TObject descendants. Interfaces, records and COM types work fine, though.

Mason Wheeler
I'd like strong emphasis on the second paragraph. If you don't see a feature exposed in the Windows API, don't expose it in your own DLL, either. Pretend you're writing a DLL to be consumed by C, or even by some environment you've never even seen before.
Rob Kennedy
+1. It may be worth pointing out too that there should (must) not be any Delphi specific types in interface method parameters and function results nor as parts of those records, either.
mghie
+1. Perhaps unrelated, but don't forget to declare all (non-COM) DLL exports as stdcall if you're going to consume them in languages other than Delphi.
Mihai Limbășan
I thought so. I think DLL could be a silver bullet in windows environment. BPL only works with the same Delphi version. Ok, in my case the only intention is to ease when I patch the class. Not to share to other version of Delphi. Thank you guys.Ok, I'll try to use PAnsiChar or to make the DLL in the lower version, then try it in the RAD2010.
WishKnew
+2  A: 

You ask:

Once again, I have a question : what principles should be followed in order to make an encapsulation of a class in a dll compatible to other version of Delphi?

and there is only one: Don't do it. You can't do it. Either you write a DLL, then use idioms and data types that can safely be used in DLLs, which precludes (among other things) classes.

Or you write a BPL, then you can safely export classes, use strings and such, but you are tied to the same Delphi version. This limitation is of technical nature, so writing a DLL will not work around it. There may be tricks to overcome this, and there may be different Delphi versions that use the same class layout so that it works, but you must not tie your public DLL interface to such implementation details.

mghie
+2  A: 

Stick with only fundamental types. If you use interfaces, create them using the type library editor so your constrained by the compatible types by the start. A good rule of thumb is to look at the windows API and try to emulate its calling conventions.

You can use classes in your DLL, you just can't expose them as such. A good idiom that works well for DLL's is the handle concept. Your DLL creates an object and returns a handle to that object. When you need to work with that object again, you pass a function in the DLL a handle. Just remember that your DLL needs to be completely responsible for the memory and lifetime of the object. Its a trivial process to create DLL functions to expose the pieces of the class that you will need access too.

From the Delphi side, you can then write a proxy wrapper which hides the handle from the user. For events you can use a callback method. Basically you pass non object function pointers to the dll, which then invokes the function on the event. A quick overview of this process is available on Delphi 3000.

skamradt
Ok noted. Thank you.
WishKnew