Recent

Author Topic: binding C library  (Read 1611 times)

gour

  • New Member
  • *
  • Posts: 17
binding C library
« on: September 18, 2020, 08:32:12 am »
Hello,

I'd like to work on multi-platform GUI project using Lazarus and for the low-level computations I need to bind 3rd party C library.

Moreover, I'd like to provide thicker or Pascal-ish bindings and not just thin wrapper ove C  API, so wonder where I can look about the general procedures how to do it, some helper tools etc.?

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: binding C library
« Reply #1 on: September 18, 2020, 08:46:22 am »
You will need:
- the C header file
- h2pas (and possibly h2paspp) to parse it. (and cpp -E and copy/paste abilities for the nerdy ones to resolve all C macro's)
- C knowledge AND Pascal knowledge
- Patience. Even with the above tools, you will need manual adjustments

On the bright side is that C headers can almost always be translated into Pascal.

Once the basic header translation is done, you can objectify it on top of that.
Sqlite is a good way to start. It is an easy example of all the above. Even for persistent beginners.(Because Sqlite is exemplary well written C code)
Note such a task is not always for beginners: it needs an intermediate to advanced programming knowledge in both C and Pascal.
« Last Edit: September 18, 2020, 08:57:54 am by Thaddy »
Specialize a type, not a var.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: binding C library
« Reply #2 on: September 18, 2020, 08:51:52 am »
On Unix, the RTL can link to libc see defne "FPC_USE_LIBC". It would be a good start.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: binding C library
« Reply #3 on: September 18, 2020, 09:12:33 am »
On Unix, the RTL can link to libc see defne "FPC_USE_LIBC". It would be a good start.

I don't think that is what gour meant.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8746
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: binding C library
« Reply #4 on: September 19, 2020, 11:00:45 am »
Moreover, I'd like to provide thicker or Pascal-ish bindings and not just thin wrapper ove C  API, so wonder where I can look about the general procedures how to do it, some helper tools etc.?
Depending on the available header files, h2pas may help getting the thin wrapper. The thick part must be written by hand, and it depends on how thick you want it to be. I don't have small examples for this, there's a big one in fpgtk package, which wraps the thin wrapper into Object Pascal classes. Otherwise, you can keep the interface procedural but make the parameters more Pascalish by replacing PChar-s with strings and pointers with var parameters. For instance:
Code: Pascal  [Select][+][-]
  1. // supposed the original C library expects you to call these 3 in succession
  2. // with FreeBuf called after finished playing with FillBuf result
  3. procedure AllocBuf(p: PChar); cdecl; external;
  4. procedure FillBuf(p: PChar); cdecl; external;
  5. procedure FreeBuf(p: PChar); cdecl; external;
  6.  
  7. // with this wrapper, Pascal side can call just a single function without worrying about forgetting to call FreeBuf
  8. // because FillBuf data has been copied as a Pascal string, therefore is no longer a subject to C memory manager
  9. procedure PascalWrapper: String;
  10. var
  11.   tmp: PChar;
  12. begin
  13.   AllocBuf(tmp);
  14.   FillBuf(tmp);
  15.   Result := StrPas(tmp);
  16.   FreeBuf(tmp);
  17. end;
  18.  

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: binding C library
« Reply #5 on: September 19, 2020, 12:54:37 pm »
[ there's a big one in fpgtk package,
That one is way to complex for most, hence I mentioned the bindings for SQlite: both serious and understandable.
Your simple example may be too simple here. (but is correct)

There are many more good examples in the standard provided packages, btw.
Specialize a type, not a var.

gour

  • New Member
  • *
  • Posts: 17
Re: binding C library
« Reply #6 on: September 29, 2020, 09:14:58 am »
You will need:
- the C header file
- h2pas (and possibly h2paspp) to parse it. (and cpp -E and copy/paste abilities for the nerdy ones to resolve all C macro's)
- C knowledge AND Pascal knowledge
- Patience. Even with the above tools, you will need manual adjustments

Thank you!

Quote
On the bright side is that C headers can almost always be translated into Pascal.

That's something which I like and decided to use FPC/Lazarus over Python...

Quote
Once the basic header translation is done, you can objectify it on top of that.

That was my gut feeling as well.  ;)

Quote
Sqlite is a good way to start. It is an easy example of all the above. Even for persistent beginners.(Because Sqlite is exemplary well written C code)

Will take a look...

Quote
Note such a task is not always for beginners: it needs an intermediate to advanced programming knowledge in both C and Pascal.

I am aware of that, but I simply have a need to bind that 3rd party C library for my project.

Otoh, FPC/Lazarus seem to be much better for writing multi-platform desktop apps than many other languages and, still, productive enough to compete with Python, not to speak about end result (aka performance). ::)

Now, I've just did a light testing to see what I get...installed H2Pas, executed the wizard and h2pas reports the following error: TRegExpr exec: empty input string.

I've tried with by adding Remove empty C macros, but it does not help.  :'(

I know it won't be smooth, but just wonder if you can give some hint about potential problem?  ;D

BobDog

  • Sr. Member
  • ****
  • Posts: 394
Re: binding C library
« Reply #7 on: September 29, 2020, 09:58:39 am »
FreeBASIC uses msvcrt.dll freely.
The bindings are all in the inc/crt folder.
Here are the layouts of the declarations in mem.bi
extern "C"

declare function memchr (byval as const any ptr, byval as long, byval as size_t) as any ptr
declare function memcmp (byval as const any ptr, byval as const any ptr, byval as size_t) as long
declare function memcpy (byval as any ptr, byval as const any ptr, byval as size_t) as any ptr
declare function memmove (byval as any ptr, byval as const any ptr, byval as size_t) as any ptr
declare function memset (byval as any ptr, byval as long, byval as size_t) as any ptr

end extern

where extern C can be equated with a cdecl at each function.

Here is a small sample of a few translations:.
Code: Pascal  [Select][+][-]
  1.  
  2.  
  3.   function Printf(mask : pchar):integer; cdecl; varargs; external 'msvcrt.dll' name 'printf';
  4.   function  memcpy(T:pointer;F:pointer;sz:integer):integer ; cdecl external 'msvcrt.dll' name 'memcpy';
  5.   function  system(s:pchar):integer ; cdecl external 'msvcrt.dll' name 'system';
  6. var
  7.   a,b:array of integer;
  8.   i:integer;
  9.  
  10.   begin
  11.   setlength(a,8);
  12.   setlength(b,8);
  13.   for i:=0 to 7 do a[i]:= i*i;
  14.    for i:=0 to 7 do printf('%d,',a[i]);
  15.   memcpy(@b,@a,8*sizeof(a));
  16.   writeln;
  17.   for i:=0 to 7 do printf('%010d '#13#10'',b[i]);;
  18.   system('pause');
  19.   end.
  20.  
  21.  

Is there a bas2pas converter out there somewhere to translate these headers?

« Last Edit: September 29, 2020, 10:36:01 am by BobDog »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: binding C library
« Reply #8 on: September 29, 2020, 12:22:15 pm »
FreeBASIC uses msvcrt.dll freely.
The bindings are all in the inc/crt folder.
Here are the layouts of the declarations in mem.bi
extern "C"

declare function memchr (byval as const any ptr, byval as long, byval as size_t) as any ptr

Free Pascal's IndexByte.

Quote
declare function memcmp (byval as const any ptr, byval as const any ptr, byval as size_t) as long

Free Pascal's CompareByte.

Quote
declare function memcpy (byval as any ptr, byval as const any ptr, byval as size_t) as any ptr

Free Pascal's Move

Quote
declare function memmove (byval as any ptr, byval as const any ptr, byval as size_t) as any ptr

Also move (move determines internally if overlap is necessary or not)

Quote
declare function memset (byval as any ptr, byval as long, byval as size_t) as any ptr

Freepascal's fillbyte

Some really tuned libc might contain faster routines, some meant to be very portable might contain smaller ones.

BUT using freepascal's primitives as much as possible (specially for small moves) might be better forwards compatible in case these functions become implement intrinsics for small constant moves at some point.

Quote
  function Printf(mask : pchar):integer; cdecl; varargs; external 'msvcrt.dll' name 'printf';

writeln for straight usage, writeln(format()) for more elaborate cases.

Quote
  function  system(s:pchar):integer ; cdecl external 'msvcrt.dll' name 'system';

ExecuteProcess or RunCommand()

IOW, all these functions are available as native functions in one way or the other.

BobDog

  • Sr. Member
  • ****
  • Posts: 394
Re: binding C library
« Reply #9 on: September 29, 2020, 02:19:08 pm »
Code: Pascal  [Select][+][-]
  1.  
  2.   function Printf(mask : pchar):integer; cdecl; varargs; external 'msvcrt.dll' name 'printf';
  3.   function  system(s:pchar):integer ; cdecl external 'msvcrt.dll' name 'system';
  4.  
  5.  
  6.   begin
  7.    printf(' Note: %s %s %c %s %s %s %c '#13#10' ','Thanks','Marcov',',','some','nice','routines','.');
  8.    printf('%s %s %s %c %c %s %s  '#13#10' ','This','was','only','a','C','binding','demo.');
  9.   system('pause');
  10.   end.
  11.  
  12.  

 

TinyPortal © 2005-2018