Exporting overloaded functions with fpc - delphi

I need to create a dll within fpc (delphi-mode). It works fine - but for some reasons, I want to do something (in a unit) like
function doSomeThing(a:type1):type2;stdcall;
function doSomeThing(a:type3):type4;stdcall;
and in the library (for building the dll using the unit above)
exports
doSomeThing(a:type1) name 'doSomeThingTYPE1',
doSomeThing(a:type3) name 'doSomeThingTYPE3';
The syntax is self explanatory and is told in How to export Overload functions from DLL? . But it seems to be unavailable in fpc (version 2.6.0-9 [2013/04/14] for x86_64). Is there a chance to do something like that - or do I have to rename the functions within my source?

The question that you link to discusses Delphi. The syntax that Delphi supports, that allows you to export overloaded functions, is not supported by FPC.
To the best of my knowledge, overloaded functions are not exportable. Although, I could easily be wrong on that score. Perhaps there is a way, as Marco proposes in his answer.

David consulted me in another thread, I devised something that compiles, but don't know if it works.
It is based on exporting the function using a defined linker level identifier, and then declaring an external function reimporting it with different Pascal names. Note that bla and bla2 doesn't even have to be in the same unit as dosomething variants.
library testdll;
{$mode delphi}
type
type1=integer;
type3=char;
type2=smallint;
type4=widechar;
function doSomeThing(a:type1):type2;stdcall; overload; [public, alias:'bla'];
begin
result:=a+1;
end;
function doSomeThing(a:type3):type4;stdcall; overload; [public, alias:'bla2'];
begin
result:=widechar(ord(a)+1000);
end;
procedure bla; external name 'bla';
procedure bla2; external name 'bla2';
exports
bla name 'doSomeThingTYPE1',
bla2 name 'doSomeThingTYPE3';
end.

Related

Delphi 10.2.3: Where is in Delphi the function VarType ()?

I am trying to convert Delphi2005 code to Delphi Tokyo 10.2.3 code.
The function VarType is no longer recognized.
I need the function VarType to determine the basic type of a variant variable. In general I find, according to many postings, that it should be in the unit System.Variants. However, if I search e.g. in:
http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/!!FUNCTIONS_System.html
It is not in this unit. Furthermore, I cannot find the unit variants, only a unit variant.
However, using the unit variant I get a runtime error:
Record, object or class type necessary
. So this doesn't work.
if (System.Variant.VarType(Value) and varTypeMask) =
System.Variant.varString then // VarType(Value) unbekannt
begin
TByte8Array(PRecFORMULA3(PBuf).Value)[0] := 0;
end;
Anyway I don't find VarType in System.variant. Does variants not exist anymore?
Can anyone help me?
The documentation you linked to is quite old. It is for Delphi 2009, which predates the introduction of Unit Scope Names. But even in that old documentation, VarType() is documented as being in the Variants unit (not in the Variant unit, which does not exist).
Unit Scope Names, like System, were added to RTL/VCL unit names in XE2 (thus, the Variants unit became System.Variants).
Embarcadero's newer DocWiki, which replaces the old Docs site, clearly shows that the VarType() function is indeed located in the System.Variants unit.
Make sure that either:
you have System.Variants in your uses clause:
uses
..., System.Variants;
you have System in your project's list of Unit Scope Names, and then you can use Variants in your uses clause:
uses
..., Variants;
Either way, you can then use VarType() as expected, without having to fully qualify it:
if (VarType(Value) and varTypeMask) = varString then
begin
TByte8Array(PRecFORMULA3(PBuf).Value)[0] := 0;
end;

can i implement `_exit`c function in delphi?

I want to consume c obj files in delphi xe3.
When linked obj files, shows this error:
`[dcc32 Error] Unit1.pas(149): E2065 Unsatisfied forward or external declaration: '_exit'`
can i implement _exit function?
Yes you can indeed do this. Typically you will link the .obj file to a single unit in your project. Implement the exit function in that unit and the Delphi linker will find it.
....
implementation
....
{$LINK foo.obj}
procedure _exit(status: Integer); cdecl;
begin
// your implementation goes here
end;
As I've illustrated this you place the function in the implementation section of the unit. It does not need to be visible externally to the unit.
You might have multiple different units that link to C objects, in which case you can place your C runtime functions, like exit, in a single unit, and use that from each other unit that links to C objects. In that scenario then you need to expose each function in the interface section so that the linker can see the function.

What is the correct way to export an object in Delphi? [duplicate]

Is it possible to put some classes into a DLL?
I have several custom classes in a project I am working on and would like to have them put in a DLL and then accessed in the main application when needed, plus if they are in a DLL I can reuse these classes in other projects if I need to.
I found this link: http://www.delphipages.com/forum/showthread.php?t=84394 which discusses accessing classes in a DLL and it mentions delegating to a class-type property but I could not find any further information on this in the Delphi help or online.
Is there any reason I should not put classes in a DLL, and if it is ok is there a better way of doing it then in the example from the link above?
Thanks
It is not possible to get a Class/Instance from a DLL.
Instead of the class you can hand over an interface to the class.
Below you find a simple example
// The Interface-Deklaration for Main and DLL
unit StringFunctions_IntfU;
interface
type
IStringFunctions = interface
['{240B567B-E619-48E4-8CDA-F6A722F44A71}']
function CopyStr( const AStr : WideString; Index, Count : Integer ) : WideString;
end;
implementation
end.
The simple DLL
library StringFunctions;
uses
StringFunctions_IntfU; // use Interface-Deklaration
{$R *.res}
type
TStringFunctions = class( TInterfacedObject, IStringFunctions )
protected
function CopyStr( const AStr : WideString; Index : Integer; Count : Integer ) : WideString;
end;
{ TStringFunctions }
function TStringFunctions.CopyStr( const AStr : WideString; Index, Count : Integer ) : WideString;
begin
Result := Copy( AStr, Index, Count );
end;
function GetStringFunctions : IStringFunctions; stdcall; export;
begin
Result := TStringFunctions.Create;
end;
exports
GetStringFunctions;
begin
end.
And now the simple Main Program
uses
StringFunctions_IntfU; // use Interface-Deklaration
// Static link to external function
function GetStringFunctions : IStringFunctions; stdcall; external 'StringFunctions.dll' name 'GetStringFunctions';
procedure TMainView.Button1Click( Sender : TObject );
begin
Label1.Caption := GetStringFunctions.CopyStr( Edit1.Text, 1, 5 );
end;
Use runtime packages for this purpose; it's exactly what they're designed for in the first place. They get loaded automatically (or can be loaded manually), and automatically set up the sharing of the same memory manager so you can freely use classes and types between them.
You're much better off using packages (which is exactly what the IDE does for much of its functionality for that very reason).
Delphi does not support either importing or exporting classes from DLLs. To import a class from another module, you need to use packages.
While the official answer is "you can't", anything is possible of course. Frameworks like Remobjects SDK and Remobjects Hydra has been doing this for a long time. The problem is that it requires you to create an infrastructure around such a system, which is not something Delphi deals with out of the box.
The first step is memory management. A DLL is injected into the process loading it, but it does not share memory management. It has to be this way since a DLL can be created in a myriad of languages, each with their own internal mechanisms. This poses a problem with safety (i.e program writing into DLL memory and visa versa).
Secondly, interface (read: content description). How will your application know what classes it can create, class members, parameter types and so on. This is why COM requires type-libraries, which describe the content of a DLL.
Third, life-time management. If memory management for the objects created from a DLL is handled by the DLL, the DLL must also release said objects.
The above steps already exists and it's called COM. You are of course free to create as many COM DLL files as you please, just remember that these have to be registered with Windows before you use them. Either "on the fly" by your application (if you have the security rights to do so) or by your installer.
This is why COM, while representing the ultimate plugin system, is rarely used by Delphi programmers, because the technical cost of using it as a plugin system outweighs the benefits.
The alternative way
If you can assure that your DLL's are only to be used by Delphi programs, then you have a second way to explore. You have to create methods to share the memory manager of your main program with the DLL (Remobjects does this). This allows you to share objects, strings and more between the DLL and the main application.
You can then use RTTI to "map" classes stored in the DLL (the DLL must do this and generate both class and method tables) which can be invoked through a proxy class you device yourself.
All in all, unless you have plenty of free time to waste, I would either buy a system like Remobjects Hydra - or stick with packages. But can it be done another way? Of course it can. But at the cost of time and hard work.

Backport of RTTI.TRttiIndexedProperty to Delphi XE

Facts:
Successfull independent efforts to bring Rtti.TVirtualInterface introduced in Delphi XE2 to prior Delphi versions were made respectively by
Vincent Parrett in Delphi.Mocks.VirtualInterface unit (Delphi Mocks)
Stefan Glienke in DSharp.Core.VirtualInterface.pas unit (DSharp)
Findings:
TRttiIndexedProperty is derived from TRttiMember.
TRttiType and TRttiInstanceType depend on TRttiIndexedProperty.
Rtti.pas depends on TypInfo.pas where some breaking changes where also introduced.
Question:
Is there a hope that one day someone will make it possible to bring TRttiIndexedProperty on Delphi XE ?
TRttiIndexedProperty can't be back-ported to older Delphi versions because it depends on the compiler writing out RTTI data for indexed properties, what only Delphi XE2's compiler does. You can't read something that isn't there.
The only possibility you have would be to write this data by hand. So you have to write a parser that runs over all your code and generates the necessary type information for all indexed properties. And because your parser isn't the compiler you would also have to write little helper functions that write and read the indexed-property.
The output could be something like this:
TMyClass = class
private
...
public
property MyArray[Index: Integer]: TMyObject read GetMyArray write SetMyArray;
// autogenerated code
class procedure RegisterIndexedPropertyInfos(Registry: TMyRttiIndexedPropertyRegistry); static;
end;
// autogenerated code
class procedure TMyClass.RegisterIndexedPropertyInfos(Registry: TMyRttiIndexedPropertyRegistry): TMyRttiIndexedProperty;
begin
Registry.Register('MyArray', [TMyRttiIndex.Create('Index', TypeInfo(Integer))], TypeInfo(TMyObject), #TMyClass.GetMyArray, #TMyClass.SetMyArray);
end;
// When using RichRTTI you can omit this line and use the the RttiContext to find RegisterIndexedPropertyInfos
RegisterIndexedPropertyClass(TMyClass, #TMyClass.RegisterIndexedPropertyInfos);

How can I Create folders recursively in Delphi?

Need some help in creating function which can create folders recursively with giving path:
C:\TestFolder\Another\AndAnother
Delphi function MkDir returning IOerror = 3.
MkDir('C:\TestFolder\Another\AndAnother');
Use
ForceDirectories('C:\TestFolder\Another\AndAnother');
(This is a standard RTL function, found in SysUtils.pas. Hence you do not need to create your own function, even though that wouldn't have been difficult.)
SysUtils is obsolete now and ForceDirectories is not UNC aware!
There is a new library in since Delphi XE7 (or even earlyer?) called IOUtils.
IOUtils is cross-platform compatible and UNC aware.
function ForceDirectories(FullPath: string): Boolean; // Works with UNC paths
begin
TDirectory.CreateDirectory(FullPath);
Result:= DirectoryExists(FullPath);
end;
Note: The function is from Delphi LightSaber library. There are several other similar I/O functions there (like ListFilesOf(Folder)).

Resources