Author Topic: [TUT] Importing C/C++ functions into SCAR [Advanced]  (Read 1614 times)

Offline Freddy

  • Owner
  • *****
  • Posts: 2616
  • Rep: 19
    • MSN Messenger - freddy1990@gmail.com
    • AOL Instant Messenger - Freddy199O
    • View Profile
    • Email
[TUT] Importing C/C++ functions into SCAR [Advanced]
« on: June 25, 2007, 07:16:32 am »
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:

Code: (cpp) [Select]
//---------------------------------------------------------------------------

#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:
Code: (cpp) [Select]
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:
Code: (cpp) [Select]
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:
Code: (pascal) [Select]
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:
Code: (pascal) [Select]
uses
  FastShareMem,
  SysUtils;

Add that under the library line. Now we have:
Code: (pascal) [Select]
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):
Code: (pascal) [Select]
{$L CppTestPlugin\Main.obj}
Now we get the following:
Code: (pascal) [Select]
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:
Code: (pascal) [Select]
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:
Code: (pascal) [Select]
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:
Code: (pascal) [Select]
function GetFunctionCount(): Integer; stdcall; export;
begin
  Result := 1;
end;

The FunctionInfo function:
Code: (pascal) [Select]
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:
Code: (pascal) [Select]
exports GetFunctionCount;
exports GetFunctionInfo;

Now our plugin is finished:
Code: (pascal) [Select]
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:
Code: (pascal) [Select]
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.

Quote
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. ;)
« Last Edit: June 25, 2007, 09:53:29 am by Freddy1990 »

Freddy1990.com

[TUT] Importing C/C++ functions into SCAR [Advanced]
« on: June 25, 2007, 07:16:32 am »

Offline Smartzkid

  • Full Member
  • ***
  • Posts: 245
  • Rep: 0
    • View Profile
Re: [TUT] Importing C/C++ functions into SCAR [Advanced]
« Reply #1 on: June 29, 2007, 09:32:44 pm »
No replies?

Wow.

Just curious, will this work only with C, or will it work with, say...assembly (hla)?

Also, if you get the time, would you mind making a quick tutorial on api calls? I've been messing with them for the past few days and found that they can be a lot of fun; I just don't know exactly how much I can do with them yet, so I'm not sure if they're really useful at all...

:p Only one more question left (okay, two):

With API calls, would it be possible to call a function from any dll? It seems it to me, but I haven't been able to try it out.

(completely unrelated) How would one make a form window (fsNone) snap to certain borders (sides, parent windows, etc)?

Freddy1990.com

Re: [TUT] Importing C/C++ functions into SCAR [Advanced]
« Reply #1 on: June 29, 2007, 09:32:44 pm »

Offline Se7eN

  • Global Moderator
  • *****
  • Posts: 464
  • Rep: 2
  • Cpp Guru
    • View Profile
    • Email
Re: [TUT] Importing C/C++ functions into SCAR [Advanced]
« Reply #2 on: July 26, 2007, 12:09:17 pm »
freddy this is pretty sick this is some thing i am most definately going to look into....
keep an eye out for the SvNPlg plugin lol

-Se7eN
Quote from: TheGuyWhoGotOn
Ok you look like you're going to break a lot of rules so here is a heads up, next time if you try to log in and cant, its because your banned.

Offline nic35025

  • Leecher
  • Posts: 1
  • Rep: 0
    • View Profile
    • Email
Re: [TUT] Importing C/C++ functions into SCAR [Advanced]
« Reply #3 on: March 24, 2009, 09:15:49 am »
Simple in C. ( I using Borland Builder to make example)
//---------------------------------------------------------------------------
#include <windows.h>
#pragma hdrstop

#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
  return 1;
}
//---------------------------------------------------------------------------
int PASCAL TimeCountGet(void) { return GetTickCount(); }

typedef struct {
  void *Addr;
  char *Desc;
} TAddrDesc;

static TAddrDesc Info[] = {
  { TimeCountGet, "function TimeCountGet :Integer;" }
};

_export _stdcall GetFunctionCount(void) {
  return sizeof(Info)/sizeof(Info[0]);
}

_export _stdcall GetFunctionInfo( int No, void *(*ProcAddr), char *(*ProcDef) ) {
  if( GetFunctionCount() > No ) {
    *ProcAddr = Info[No].Addr;
    strcpy( *ProcDef, Info[No].Desc );
    return No;
  }
  return -1;
}

Offline Dan Cardin

  • Magical Yams
  • Global Moderator
  • *****
  • Posts: 417
  • Rep: 0
  • I is am are you!
    • MSN Messenger - thelonelydingo33@hotmail.com
    • AOL Instant Messenger - YoYoPotatoTomato
    • View Profile
    • DanCardin
    • Email
Re: [TUT] Importing C/C++ functions into SCAR [Advanced]
« Reply #4 on: March 24, 2009, 12:35:15 pm »
does this mean that i could write a program in C++ and basically run it in SCAR?

Freddy1990.com

Re: [TUT] Importing C/C++ functions into SCAR [Advanced]
« Reply #4 on: March 24, 2009, 12:35:15 pm »

Offline Smartzkid

  • Full Member
  • ***
  • Posts: 245
  • Rep: 0
    • View Profile
Re: [TUT] Importing C/C++ functions into SCAR [Advanced]
« Reply #5 on: May 25, 2009, 12:32:52 am »
Yup. (string passing is a pain though)

Freddy1990.com

Re: [TUT] Importing C/C++ functions into SCAR [Advanced]
« Reply #5 on: May 25, 2009, 12:32:52 am »