Jump to content

Recommended Posts

logo.thumb.png.cdc64ace8bb901436193a3c613a8b492.png

Overview

What if you were able to load and use C99 sources directly from Delphi? There is a vast quantity of C libraries out there and being able to take advantage of them, without being a pain would be nice. You could even compile a bunch of sources and save them as a library file, then load them back in from disk, a resource or even from a stream. You can get the symbols, map to a C routine, and execute from the Delphi side all from a simple API.

 

Downloads

Releases - These are the official release versions.

 

Features

  • Free for commercial use.
  • Allow C integration with Delphi at run-time.
  • Support Windows 64-bit platform.
  • Support for C99.
  • Fast run-time compilation.
  • Can run C sources directly or compile to (.LIB, .EXE, .DLL).
  • Library files can be loaded and used at run-time from a file, a resource or stream.
  • Import symbols directly from a dynamic linked library (.DLL) or module-definition (.DEF) file.
  • You can reference the symbols from Delphi and directly access their value (mapping to a routine and data).
  • Your application can dynamically or statically link to CPas.
  • Direct access to the vast quantity of C99 libraries inside Delphi.

 

Minimum System Requirements

  • Delphi 10 (Win64 target only)
  • FreePascal 3.3.3 (Win64 target only)
  • Microsoft Windows 10, 64-bits
  • 20MB of free hard drive space

 

How to use in Delphi

  • Unzip the archive to a desired location.
  • Add installdir\sources, folder to Delphi's library path so the CPas source files can be found for any project or for a specific project add to its search path.
  • Add installdir\bin, folder to Windows path so that CPas.dll file can be found for any project or place beside project executable.
  • See examples in installdir\examples for more information about usage.
  • You must include CPas.dll in your project distribution when dynamically linked to CPas. See CPAS_STATIC define in the CPas unit file.
  • See installdir\docs for documentation.

 

A Tour of CPas

CPas API

You access the easy to use API in Delphi from the CPas unit.

{.$DEFINE CPAS_STATIC} //<-- define for static distribution

type
  { TCPas }
  TCPas = type Pointer;

  { TCPasOutput }
  TCPasOutput = (cpMemory, cpLib);

  { TCPasExe }
  TCPasExe = (cpConsole, cpGUI);

  { TCPasErrorMessageEvent }
  TCPasErrorEvent = procedure(aSender: Pointer; const aMsg: WideString);

{ Misc }
function cpVersion: WideString;

{ State management }
function  cpNew: TCPas;
procedure cpFree(var aCPas: TCPas);
procedure cpReset(aCPas: TCPas);

{ Error handling }
procedure cpSetErrorHandler(aCPas: TCPas; aSender: Pointer; aHandler: TCPasErrorEvent);
procedure cpGetErrorHandler(aCPas: TCPas; var aSender: Pointer; var aHandler: TCPasErrorEvent);

{ Preprocessing }
procedure cpDefineSymbol(aCPas: TCPas; const aName: WideString; const aValue: WideString);
procedure cpUndefineSymbol(aCPas: TCPas; const aName: WideString);
function  cpAddIncludePath(aCPas: TCPas; const aPath: WideString): Boolean;
function  cpAddLibraryPath(aCPas: TCPas; const aPath: WideString): Boolean;

{ Compiling }
procedure cpSetOuput(aCPas: TCPas; aOutput: TCPasOutput);
function  cpGetOutput(aCPas: TCPas): TCPasOutput;
procedure cpSetExe(aCPas: TCPas; aExe: TCPasExe);
function  cpGetExe(aCPas: TCPas): TCPasExe;
function  cpAddLibrary(aCPas: TCPas; const aName: WideString): Boolean;
function  cpAddFile(aCPas: TCPas; const aFilename: WideString): Boolean;
function  cpCompileString(aCPas: TCPas; const aBuffer: string): Boolean;
procedure cpAddSymbol(aCPas: TCPas; const aName: WideString; aValue: Pointer);
function  cpLoadLibFromFile(aCPas: TCPas; const aFilename: WideString): Boolean;
function  cpLoadLibFromResource(aCPas: TCPas; const aResName: WideString): Boolean;
function  cpLoadLibFromStream(aCPas: TCPas; aStream: TStream): Boolean;
function  cpSaveOutputFile(aCPas: TCPas; const aFilename: WideString): Boolean; 
function  cpRelocate(aCPas: TCPas): Boolean;
function  cpRun(aCPas: TCPas): Boolean;
function  cpGetSymbol(aCPas: TCPas; const aName: WideString): Pointer;

{ Stats }
procedure cpStartStats(aCPas: TCPas);
function  cpEndStats(aCPas: TCPas; aShow: Boolean): WideString;

If you want CPas to be statically bound to your application, enable the {$CPAS_STATIC} define in the CPas unit.

 

How to use

A minimal implementation example:

uses
  System.SysUtils,
  CPas;

var
  c: TCPas;
  
// CPas error handler
procedure ErrorHandler(aSender: Pointer; const aMsg: WideString);
begin
  WriteLn(aMsg);
end;  
  
begin
  // create a CPas instance
  c := cpNew;
  try
    // setup the error handler
    cpSetErrorHandler(c, nil, ErrorHandler);
    
    // add source file
    cpAddFile(cp, 'test1.c');

    // link and call main
    cpRun(cp);
  finally
    // destroy CPas instance
    cpFree(c);
  end;
end.

 

Compatibility

These are some libraries that I've tested. If you have tried more, let me know and I can add them to the list.

 

Media

 

 

 

delphi.png.adfd5fcbe0667689de1529ec76cbb49e.png

❤ Made in Delphi

Edited by tinyBigGAMES
  • Like 9

Share this post


Link to post

Version 1.2.stable released! 😯

  • Added updated existing examples to use new/updates functions
  • cpGetVersionInfo, get version information
  • cpSetVersionInfo, set version information
  • cpGetAddVersionInfo, get add version info
  • cpSetAddVersionInfo, set add version info
  • Added cpGetExeIcon, get EXE icon filename
  • Added cpSetExeIcon, set EXE icon filename
  • Miscellaneous enhancements
  • Like 1

Share this post


Link to post
On 3/6/2022 at 5:09 PM, tinyBigGAMES said:

Support Windows 64-bit platform.

I assume that means it will not work with 32 bit applications running on 32 bit or 64 bit Windows.

Share this post


Link to post
10 minutes ago, Mark- said:

I assume that means it will not work with 32 bit applications running on 32 bit or 64 bit Windows.

Hi, yes that is correct. It generates 64-bit binaries only and therefore can only run on 64-bit windows and bind to 64-bit DLLs/Libs.

Share this post


Link to post
1 hour ago, tinyBigGAMES said:

Hi, yes that is correct. It generates 64-bit binaries only and therefore can only run on 64-bit windows and bind to 64-bit DLLs/Libs.

Awww...

Share this post


Link to post

Would be nice to know what's actually going on here, but all I can see is an opaque DLL which seems to have all the implementation in it.

  • Like 2

Share this post


Link to post
2 hours ago, David Heffernan said:

Would be nice to know what's actually going on here, but all I can see is an opaque DLL which seems to have all the implementation in it.

I had the same curiosity and asked the author on facebook. It actually contains a modified version of Tiny C Compiler, but I didn't ask for implementation details.

 

That being said, the OP might can give us more details.

Share this post


Link to post

That API allows you, from Delphi to compile C99 sources, or load in precompiled sources at runtime. As such, you have access to a lot of C99 libraries you can now, with ease take advantage of. It's small and fast, so it can be used as a scripting solution if you wish. You have access to the symbols, so code and data can be exchanged between Delphi and C. There are examples in the distro that demonstrates all these features. Think of it like using Lua from Delphi, it's just easier, cooler much more powerful. It leverages Tiny C Compiler for the backend code generation.

Edited by tinyBigGAMES
  • Thanks 1

Share this post


Link to post

So it's more geared towards looser coupling, a more scripting like approach. I guess if I know the external code I want to use at compile time then linking to a DLL in the classic fashion is generally preferable. 

  • Like 1

Share this post


Link to post
6 hours ago, David Heffernan said:

So it's more geared towards looser coupling, a more scripting like approach. I guess if I know the external code I want to use at compile time then linking to a DLL in the classic fashion is generally preferable. 

I made CPas becaue I found using C/C++ build system is too complicated. I just want to "use" the library and not mess about trying to figure out how to compile it. If, when you do get it compiled and stuff changes, you must go through the whole dreaded process again. Why can't it be as easy as using Delphi? So you think, but there is C++ Builder. Have you tried to compile open source libraries with it? The ones that I have tried, I could not get to compile, I end up having to use Visual Studio, which means you must install all of that. I just want to use the library, LOL. 

 

To use with Delphi, the sources would normally have to be compiled to a DLL, well you can make DLLs with CPas. You can make .EXEs, and .LIBs also. Like I said before, using CPas to compile these C99 libs is much easier. This was my motivation for making it. If you created a .LIB, it can be loaded from a stream, a resource etc. Now you do not have to have an extra DLL footprint in your distro if do not want to. Again, the flexibility, you can use it how you want to. If you need to compile some sources at runtime for a "scripting" scenario, well you can do that too. The possibilities, from an easy to use API. 

Edited by tinyBigGAMES
  • Like 1

Share this post


Link to post
4 hours ago, tinyBigGAMES said:

I made CPas becaue I found using C/C++ build system is too complicated. I just want to "use" the library and not mess about trying to figure out how to compile it. If, when you do get it compiled and stuff changes, you must go through the whole dreaded process again. Why can't it be as easy as using Delphi? So you think, but there is C++ Builder. Have you tried to compile open source libraries with it? The ones that I have tried, I could not get to compile, I end up having to use Visual Studio, which means you must install all of that. I just want to use the library, LOL. 

I tend to use msys2 to build such libraries. Generally very simple to get it built. 

  • Like 1

Share this post


Link to post
3 minutes ago, David Heffernan said:

I tend to use msys2 to build such libraries. Generally very simple to get it built. 

Ok, then.

 

19 minutes ago, Anders Melander said:

And this was the easy way?

I made CPas for the reasons I've described.

Share this post


Link to post
5 hours ago, Mark- said:

I think it is interesting but we need 32 bit.

It's 2022. Why does anyone need 32 bit? Windows isn't even available in 32bit anymore starting with Windows 11.

  • Like 1

Share this post


Link to post
12 hours ago, tinyBigGAMES said:

I made CPas becaue I found using C/C++ build system is too complicated. I just want to "use" the library and not mess about trying to figure out how to compile it.

Nice! I'm reminded a bit of the cppyy package for Python, which solved some of the same types of problems by the unorthodox method of embedding cling, a C++ interpreter built on top of clang.
 

Quote


automatic, run-time, Python-C++ bindings generator.... Run-time generation enables detailed specialization for higher performance, lazy loading for reduced memory use in large scale projects, Python-side cross-inheritance and callbacks for working with C++ frameworks, run-time template instantiation, automatic object downcasting, exception mapping, and interactive exploration of C++ libraries. cppyy delivers this without any language extensions, intermediate languages, or the need for boiler-plate hand-written code.

 

 

 

Share this post


Link to post

As I understand it, although it's being released on github, this project is not open source, right?

  • Sad 1

Share this post


Link to post
1 hour ago, Joseph MItzen said:

Nice! I'm reminded a bit of the cppyy package for Python, which solved some of the same types of problems by the unorthodox method of embedding cling, a C++ interpreter built on top of clang.
 

 

 

Ahh, sweet!

Share this post


Link to post
3 minutes ago, Edwin Yip said:

As I understand it, although it's being released on github, this project is not open source, right?

Correct.

Share this post


Link to post
6 hours ago, Joseph MItzen said:

It's 2022. Why does anyone need 32 bit? Windows isn't even available in 32bit anymore starting with Windows 11.

Your view of the landscape appears to be limited.

  • Haha 1

Share this post


Link to post
7 hours ago, Joseph MItzen said:

It's 2022. Why does anyone need 32 bit? Windows isn't even available in 32bit anymore starting with Windows 11.

Often because of dependencies on 32 bit code. Like how the Delphi IDE is. 

 

Personally I think  could drop 32 bit support now and my customers would be fine with it. 

  • Like 1

Share this post


Link to post
On 3/12/2022 at 7:11 AM, Mark- said:

Your view of the landscape appears to be limited.

I think my view of the landscape is 32 bits less limited than your view. :classic_tongue:

  • Haha 1

Share this post


Link to post
On 3/11/2022 at 7:38 PM, Mark- said:

I think it is interesting but we need 32 bit.

Refactoring code base with 32-bit support, will be in the next update! :classic_cool:

  • Thanks 1

Share this post


Link to post
1 hour ago, Joseph MItzen said:

I think my view of the landscape is 32 bits less limited than your view. :classic_tongue:

 Benjamin says otherwise.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×