The DLL exports functions by name and ordinal value. Each of them must be unique. You cannot export two different functions with the same name or the same serial number.
Your InterlockedExchangeAdd example is just two functions with different but equivalent signatures related to the same function. This is done for the convenience of the caller.
Leave the ordinal one way and focus on the names. From the first paragraph it is very clear that you need to use different names for each function. Of course, you can still use overloading internally, but specify individual names as part of the export clause. Similarly, when importing, you can declare the imported functions as overloaded, but use the name syntax to specify the name of the DLL.
So, in general, you can easily use overloading internally on both sides of the interface, but when exporting and importing functions, you need to use unique names. Here is a simple example:
Library that exports functions
library liba; procedure F(X: Integer); stdcall; overload; begin end; procedure F(X, Y: Integer); stdcall; overload; begin end; exports F(X: Integer) name 'F1', F(X, Y: Integer) name 'F2'; begin end.
Library that imports functions
library libb; procedure F(X: Integer); stdcall; overload; external 'liba.dll' name 'F1'; procedure F(X, Y: Integer); stdcall; overload; external 'liba.dll' name 'F2'; begin end.
The overload can appear anywhere in the ad. It doesn't matter where he appears. On the other hand, the calling convention must appear before external .
Note that languages โโthat do not support overloading (i.e. VB6, C), obviously, will not be able to import functions and use the same names for them. Similarly for languages โโthat do not support renaming a function upon import (i.e. C ++). As far as I know, only Delphi actually allows such neat tricks during import.
For languages โโlike C ++ and C # that support overloading, you will need to introduce another layer of indirection. For example, in C # you do the following:
[DllImport("liba.dll")] private static extern void F1(int X); [DllImport("liba.dll")] private static extern void F2(int X, int Y); public static void F(int X) { F1(X); } public static void F(int X, int Y) { F2(X, Y); }
Exactly the same approach can be used in C ++. The only real difference between this approach and the Delphi code shown above is that the Delphi language supports direct syntax for this mapping.
As for the various examples in your question, they all use a string, which, of course, is a private Delphi type. You should not use string in the exported function if the function should be called from any language other than Delphi. Or really, any version of the compiler other than the one with which you built the DLL.