3

This will be my first attempt to code a DLL in Delphi for calling from other languages.

I have done a lot of googling and see a few good pointers, but nothing exhaustive (at least, I have questions that don't find answered in the Embarcadero material).

I wonder if this list of caveats is exhhaustive, or if I missed anything, and if anyone can anser my questions below.

  • if I want my DLL to be callable from other languages, then i can't use the ShareMem unit.
  • I can't use the String type and should stick with PChar
  • if I want to return a string, the caller should pass me a buffer to write it to (I should not alloctae the memory for it myself, even if I provide a routine to free it afterwards)
  • I should stick to simple types like integetr and PChar (any others?)

A few questions:

  • the comipler forbids me to export enums and constants. Am I just not declaring them correctly? I would like calling Delphi s/w to be able to use the enum elements and all callers to be able to use constants.
  • I should not use any structures because of possible differences in byte alignment between compilers. So, if I can't accept strctures as parameters. I guess I should just have a long parameter list of integers and PChars?
  • can I accept arrays as parameters, or does boundary alignment make that dangerous?
  • can I accept/return floats/doubles ?
  • booleans? Or am I stuck with "zer0 === false and all else is true"?

  • is there anything else I should know?

Thanks in advance for any help

Mawg says reinstate Monica
  • 38,334
  • 103
  • 306
  • 551
  • 2
    All of your conclusions in your "questions" are wrong (except possibly the first one, which asks if you're declaring something wrong - you didn't show how you're declaring it, so we can't determine). You can do all of those things. It would be better if you asked a more specific question about actual problems you're having with your code instead. – Ken White Nov 30 '13 at 07:51
  • +1 Ken, as always, you are the guru. I am aware that question is too broad in it's scope. I just wanted to ask - what's the definitive book or URL? How do I (how did you) learn to do this? – Mawg says reinstate Monica Nov 30 '13 at 12:52
  • 1
    There is no definitive book on interop. All the experts learnt the same way. By picking it up piece by piece as they went along. – David Heffernan Nov 30 '13 at 14:00

1 Answers1

8

The compiler forbids me to export enums and constants. Am I just not declaring them correctly? I would like calling Delphi s/w to be able to use the enum elements and all callers to be able to use constants.

You cannot export enumerated types and constants. The caller will have to declare them again. The same goes for types.

I should not use any structures because of possible differences in byte alignment between compilers.

Feel free to use records. Alignment is standardised across compilers on the same platform. Do make sure that you use a modern Delphi, XE2 or later, that follows the platform standard for alignment correctly.

So, if I can't accept strctures as parameters. I guess I should just have a long parameter list of integers and PChars?

You can receive records as parameters.

Can I accept arrays as parameters, or does boundary alignment make that dangerous?

You can accept arrays. You need to receive a pointer to the first element, and the number of elements. Array elements are always layed out immediately following the previous elements.

Can I accept/return floats/doubles? Booleans? Or am I stuck with "zero === false and all else is true"?

Yes you can use floating point types and booleans.

Is there anything else I should know?

Almost certainly.

I'll mention one more issue, but there surely are more. Don't use records as return types to functions. Delphi does not follow the platform standard in its handling of function return types for records. Use an out parameter instead.


A good way to learn by example what can be done is to study the Windows API.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 2
    This is a general question and so here's a general answer. Detailed follow ups would best be handled in specific questions with specific code examples. – David Heffernan Nov 30 '13 at 08:29
  • "Don't use records as return types to functions. Delphi does not follow the platform standard in its handling of function return types for records." Could you expand on this please? I'm not aware of any problem using returning records, and if there is one I'd like to be :) – David Nov 30 '13 at 11:00
  • @David Delphi passes records as extra implicit var params. The standard platform, as per MS C++ compiler differs. You'll have problems with large records when doing interop with C++, C# etc. Same for WideString. Take a look at my questions sorted by votes to see coverage of WideString return values which is the same issue. – David Heffernan Nov 30 '13 at 11:09
  • Thanks. I just searched through the top ten pages of your answers sorted by votes (highest first), and found only [one referring to WideString](http://stackoverflow.com/questions/9331026/why-can-delphi-dlls-use-widestring-without-using-sharemem/9331077#9331077) at all (plus the one it linked to at the top.) Could you point me at the answer you're referring to please? – David Nov 30 '13 at 11:25
  • The last sentence ("look at Windows API") was always on my mind reading the question and this answer ... got a matching sound in my head ;o) – Sir Rufo Nov 30 '13 at 12:00
  • 1
    @DavidM Sorry, was on my phone. Yes, it was a question I asked. Here: http://stackoverflow.com/questions/9349530/why-can-a-widestring-not-be-used-as-a-function-return-value-for-interop – David Heffernan Nov 30 '13 at 13:59
  • Thanks. Interesting stuff - I didn't know that! – David Nov 30 '13 at 14:59
  • Just curious. How do you know this. Is there a book or a good website explaining it? – Mawg says reinstate Monica Dec 01 '13 at 02:45