PDA

View Full Version : Importing C/C++ functions into SCAR



Freddy1990
06-25-2007, 01:58 PM
Welcome to another tutorial by me :)
Been a while since my last turorial, but here goes:

For some time it has been possible to write plugins in delphi which export functions and can be loaded by SCAR. This allows you to seriously expand the possibilities of SCAR by utilising the power of non-interpreted processing which is very useful for intensive works like image-processing. However, not everyone likes to code in Delphi, some prefer other languages like C++. Therefor I have done some research to come up with the following. In this tutorial I will explain how to export C++ functions to delphi and how to load them trough a SCAR plugin.

First of all, we need a C++ compiler. For this example I will use Borland C++ Builder 6 which is somewhat the C++ equivalent of Borland Delphi 7. It should be possible to use other compilers as well though. We are going to simply make 1 file in this tutorial with our function, to keep it easy we're going to use a .c file. However, to make the file compile we will need to have a project file as well, unless you are using for example a commandline compiler.

First we open Borland C++ Builder 6. We choose File => New => Other... . Here we click (to keep it easy), "Library". The following should appear in the compiler:


//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#define Library

// To add a file to the library use the Project menu 'Add to Project'.

Now we simply save this in a subfolder of our SCAR plugin folder, to keep it structurised we name the folder after the SCAR plugin we will write later "CppTestPlugin". I named the projectfile "Cpp_Lib", though it doesn't matter how you name it. Now that we have our project to compile we will make a new file where our actual code will be located. We choose File => New => Other... and then we select "C File". Now we get an empty file, we'll save this in the same folder as the project, to keep it easy I named the file "Main.c". Now we go into the Project menu and click "Add to project...". Then we go to our folder and select the Main.c file.

Now we have our basic C++ files set up, now we'll write a simple C++ function to export to SCAR.

The simple function I wrote increments an entered number by 10 and the returns it:

int Inc10(int Numb) {
return Numb + 10;
}

This we add to out Main.c file.

Now that we have our function to export we still need it to be exported, for that we add the following line above the function we just added:

extern int Inc10(int Numb);

That is it for the C++ part, the only thing left to do is build the results of what we've made. For that click Build in the Project menu. Now there should appear a Main.obj file in your folder with the C++ files. That's what we need. This file we will link in our Delphi plugin.

Now that we have written the C++ part we can write the Delphi part of the plugin. First to start off we open Delphi. There we choose File => New => Other... . Then we click DLL Wizard. Just delete everything between "library Project2;" and "{$R *.res}" so we have a clean environment to work with:
library Project2;

{$R *.res}

begin
end.

First of all we'll save the library, just save it in the Plugins folder, I named it "CppTestPlugin.dpr". Now we'll add the includes that the library needs to function:
uses
FastShareMem,
SysUtils;

Add that under the library line. Now we have:
library Project2;

uses
FastShareMem,
SysUtils;

{$R *.res}

begin
end.

Now we will link the obj file we made earlier with C++ to the delphi library, to do so we use the compiler directive "$L". The L stands for Link. behind that we add the path relative to the delphi project file, this we add under "{$R *.res}" (Which is the line that includes the dll's resources for example the version number and such):
{$L CppTestPlugin\Main.obj}

Now we get the following:
library Project2;

uses
FastShareMem,
SysUtils;

{$R *.res}
{$L CppTestPlugin\Main.obj}

begin
end.

Now that the obj file has been linked to our library we can import the actual C++ function we wrote. After quickly translating the function line we get: "function Inc10(Numb: Integer): Integer;" however, because it's imported from C++ we need to add _ before the function name: "function _Inc10(Numb: Integer): Integer;". Now we need to add 2 more extra keywords to make it work, cdecl and external to indicate that it's an externally loaded function from C++. So this results in the following:
library Project2;

uses
FastShareMem,
SysUtils;

{$R *.res}
{$L CppTestPlugin\Main.obj}

function _Inc10(Numb: Integer): Integer; cdecl; external;

begin
end.

Now we have our imported function, however, we can't directly export it, so we'll just make a small Entry function:
function Inc10(Numb: Integer): Integer; stdcall;
begin
Result := _Inc10(Numb);
end;

This allows us to export it by adding the stdcall keyword.

To finish off we add the default stuff needed for a SCAR plugin to export a function. The FunctionCount function:
function GetFunctionCount(): Integer; stdcall; export;
begin
Result := 1;
end;

The FunctionInfo function:
function GetFunctionInfo(x: Integer; var ProcAddr: Pointer; var ProcDef: PChar): Integer; stdcall;
begin
case x of
0:
begin
ProcAddr := @Inc10;
StrPCopy(ProcDef, 'function Inc10(Numb: Integer): Integer;');
end;
else
x := -1;
end;
Result := x;
end;

And then we export those:
exports GetFunctionCount;
exports GetFunctionInfo;

Now our plugin is finished:
library CppTestPlugin;

uses
FastShareMem,
SysUtils;

{$R *.res}
{$L CppTestPlugin\Main.obj}

function _Inc10(Numb: Integer): Integer; cdecl; external;

function Inc10(Numb: Integer): Integer; stdcall;
begin
Result := _Inc10(Numb);
end;

function GetFunctionCount(): Integer; stdcall; export;
begin
Result := 1;
end;

function GetFunctionInfo(x: Integer; var ProcAddr: Pointer; var ProcDef: PChar): Integer; stdcall;
begin
case x of
0:
begin
ProcAddr := @Inc10;
StrPCopy(ProcDef, 'function Inc10(Numb: Integer): Integer;');
end;
else
x := -1;
end;
Result := x;
end;

exports GetFunctionCount;
exports GetFunctionInfo;

end.

What remains now is to build our plugin and test it, so press Build in the Project menu. Then open SCAR. You can easilly test it with the following:
program CppPluginTest;

const
Number = 5;

begin
WriteLn(IntToStr(Inc10(Number)));
end.

You will know it works if SCAR prints out a number that's 10 more than your constant number.


Note:
When you use a commandline compiler, in my case I can use Borland C++ Builder's commandline compiler, I could directly compile the c file without using a project file by just doing:
bcc32 -c Main.c

Well, that's it for the tutorial, all files are included, have fun with it. ;)

Santa_Clause
06-25-2007, 02:03 PM
Enough 1337 tutorials dude! I'm digging this stuff that you do...becoming the next Kaitnieks are we?

Smartzkid
06-25-2007, 02:04 PM
Wow, that's pretty amazing

Thanks Freddy, even though I doubt I'll be using this anytime in the near future...

EDIT: The near future has just come. Thanks for this tut, amazing what you can do in C++ :)

Freddy1990
06-25-2007, 02:23 PM
Heh, this was on my todo list, didn't have the time to finish it before :)

BenLand100
06-27-2007, 09:34 AM
Too bad Borland uses OMF object files... Now i've got to find a c compiler that generates OMF instead of COFF ;)
EDIT: Got me a borland compiler from "somewhere". Also, why not just define the function in c as stdcall and skip the wrapper part?


extern int __stdcall getFour() {
return 4;
}


function getFour: integer; stdcall; external;

Santa_Clause
06-27-2007, 10:26 AM
Ehh! Is BenLand asking questions?!

BenLand100
06-27-2007, 11:15 AM
No, its a 'why not' ie. a suggestion :p

ronny.m.p
07-25-2007, 04:45 PM
Hmm, i'm useing visual studio and vcl is not a recognised include. Is it maybe the standerd include? Any ideas freddy?

BenLand100
07-26-2007, 01:37 AM
I don't think you actualy need the vcl include for anything, but you'll need to get the borland compiler to compile to coff object files anyway ;)

Santa_Clause
07-26-2007, 01:57 AM
I have no idea what the hell you just said Ben...

BenLand100
07-26-2007, 11:11 AM
Hmm, i'm useing visual studio and vcl is not a recognised include. Is it maybe the standerd include? Any ideas freddy?


I don't think you actualy need the vcl include for anything, but you'll need to get the borland compiler to compile to coff object files anyway ;)


I have no idea what the hell you just said Ben...
But he should ;)

ronny.m.p
07-26-2007, 11:56 AM
And I do :). I'll go get the borland compiler. Do I need Delphi too or can I just use a notepad and save it as a delphi format? I ask because the c++ builder trial dosen't let you have both.

The Element
08-12-2007, 05:02 PM
Why is a guest able to post?

Infantry001
08-12-2007, 07:33 PM
Cuz tutorial island is for everyone to see/post, even for guests (i think).

And btw, Freddy, awesome tutorial! Ill use it eventually.

Macrosoft
08-13-2007, 12:45 AM
OMG finally, iv been looking for a tut like this for like and hour!

lol, my first and fav programing language is C++, you can do so much and it so simple

in scar you gotta do all this weird stuff to make a proggy

c++ all you have to do is
int TimesDone;
cout<<"Did Watever "<<TimesDone<<" times"<<endl;

So beautifly simple

Oh and btw, can you add the "<<" in Scar Divi, i mean, it would make things easier
Oh and making Divi Object Oriented would be sweet!

lol sorry, didn't know were to post scar divi suggestions:redface:

The Element
08-13-2007, 11:49 AM
www.freddy1990.com ;)

~alex~
08-13-2007, 11:51 AM
Cuz tutorial island is for everyone to see/post, even for guests (i think).

And btw, Freddy, awesome tutorial! Ill use it eventually.

No its because ronny was here but he got banned and deleted. So now his post comes up as guest.

The Element
08-13-2007, 12:03 PM
ronymp is right though...you can only have 1 or the other. Don't we need both for this?

TheGodfather
08-27-2007, 06:54 AM
what would we ever do w/o you.

R0b0t1
09-02-2007, 11:46 PM
Hey, what about C# plugins?


Also, where might I learn how Delphi plugins based on C++ are made?

Eduard
07-04-2008, 06:57 PM
Oo watch out for the:
GetAnycKeyState() :D