Recent

Author Topic: Trying to bind a C library  (Read 6434 times)

lumi

  • New Member
  • *
  • Posts: 17
Trying to bind a C library
« on: March 22, 2021, 09:53:29 am »
Hello,

I am trying to bind a C library and I am having trouble with forward declaration.
This is the C code:
Code: C  [Select][+][-]
  1. // Forward declaration
  2. struct StructA;
  3.  
  4. typedef void (*FunctionA)(const char* name, struct StructA result);
  5.  
  6. typedef struct StructA {
  7.   FunctionA onComplete;
  8. }
  9.  

I'm a bit clueless on how to solve this cyclic dependency

Thank you!  :)

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11452
  • FPC developer.
Re: Trying to bind a C library
« Reply #1 on: March 22, 2021, 10:09:38 am »
The only forward definitions are for pointer and class instances (which are also pointers). So I don't think this is possible.

The easiest solution is to define oncomplete as a pointer, and then cast it to a procedure variable on use.

If you use it really a lot, you can define a record helper that returns a property that does the cast?

lumi

  • New Member
  • *
  • Posts: 17
Re: Trying to bind a C library
« Reply #2 on: March 22, 2021, 11:42:31 am »
I see, thanks! I will try it with a pointer and see how it goes. I think the library uses the function pointer as a callback

I managed to finish the bindings but when I run a simple test with it I get an Application error 0xc00007b(The application was unable to start correctly), and a 123 exit code in fp ide. Is it a problem with the DLL that I supplied?

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Trying to bind a C library
« Reply #3 on: March 22, 2021, 11:46:34 am »
That error might indicate a 32-bit/64-bit mismatch between dll and executable.

Zvoni

  • Hero Member
  • *****
  • Posts: 2327
Re: Trying to bind a C library
« Reply #4 on: March 22, 2021, 11:50:23 am »
Hello,

I am trying to bind a C library and I am having trouble with forward declaration.
This is the C code:
Code: C  [Select][+][-]
  1. // Forward declaration
  2. struct StructA;
  3.  
  4. typedef void (*FunctionA)(const char* name, struct StructA result);
  5.  
  6. typedef struct StructA {
  7.   FunctionA onComplete;
  8. }
  9.  

I'm a bit clueless on how to solve this cyclic dependency

Thank you!  :)

I'd actually be very surprised, if The Function actually really uses the struct instead of a Pointer

would have expected
Code: [Select]
typedef void (*FunctionA)(const char* name, StructA* result);
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

lumi

  • New Member
  • *
  • Posts: 17
Re: Trying to bind a C library
« Reply #5 on: March 22, 2021, 12:05:28 pm »
Hello,

I am trying to bind a C library and I am having trouble with forward declaration.
This is the C code:
Code: C  [Select][+][-]
  1. // Forward declaration
  2. struct StructA;
  3.  
  4. typedef void (*FunctionA)(const char* name, struct StructA result);
  5.  
  6. typedef struct StructA {
  7.   FunctionA onComplete;
  8. }
  9.  

I'm a bit clueless on how to solve this cyclic dependency

Thank you!  :)

I'd actually be very surprised, if The Function actually really uses the struct instead of a Pointer

would have expected
Code: [Select]
typedef void (*FunctionA)(const char* name, StructA* result);

This is the source code from the header of the lib:
Code: C  [Select][+][-]
  1. // Forward declare
  2. struct WrenLoadModuleResult;
  3.  
  4. // Called after loadModuleFn is called for module [name]. The original returned result
  5. // is handed back to you in this callback, so that you can free memory if appropriate.
  6. typedef void (*WrenLoadModuleCompleteFn)(WrenVM* vm, const char* name, struct WrenLoadModuleResult result);
  7.  
  8. // The result of a loadModuleFn call.
  9. // [source] is the source code for the module, or NULL if the module is not found.
  10. // [onComplete] an optional callback that will be called once Wren is done with the result.
  11. typedef struct WrenLoadModuleResult
  12. {
  13.   const char* source;
  14.   WrenLoadModuleCompleteFn onComplete;
  15.   void* userData;
  16. } WrenLoadModuleResult;
  17.  

I thought the same too, that it doesn't really make sense that it is not a pointer.

Edit:
That error might indicate a 32-bit/64-bit mismatch between dll and executable.
Can you compile 64bit executable with freepascal?
« Last Edit: March 22, 2021, 02:37:21 pm by lumi »

MarkMLl

  • Hero Member
  • *****
  • Posts: 6686
Re: Trying to bind a C library
« Reply #6 on: March 22, 2021, 01:21:05 pm »
I thought the same too, that it doesn't really make sense that it is not a pointer.

If that struct really doesn't contain anything but a reference to a function, is it being optimised away so that in effect it is a pointer?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Zvoni

  • Hero Member
  • *****
  • Posts: 2327
Re: Trying to bind a C library
« Reply #7 on: March 22, 2021, 02:23:03 pm »
I thought the same too, that it doesn't really make sense that it is not a pointer.

If that struct really doesn't contain anything but a reference to a function, is it being optimised away so that in effect it is a pointer?

MarkMLl
Don't think so, since that struct contains 3 "Fields", albeit all three are pointers.
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

MarkMLl

  • Hero Member
  • *****
  • Posts: 6686
Re: Trying to bind a C library
« Reply #8 on: March 22, 2021, 03:16:37 pm »
Don't think so, since that struct contains 3 "Fields", albeit all three are pointers.

I was looking at the original struct from OP. I agree that his more comprehensive example wouldn't optimise like I suggested.

The perils of people not posting the exact code that was giving them problems...

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

lumi

  • New Member
  • *
  • Posts: 17
Re: Trying to bind a C library
« Reply #9 on: March 22, 2021, 07:21:25 pm »
Quote
The perils of people not posting the exact code that was giving them problems...
Yes, I am sorry, I thought it would be more straight forward with "dumbed down" c code.

I tried multiple settings to compile the Wren library, but I still get the errors. I wanted to make sure that I can load .dll that have been built with VS (I also tried to load a .lib but apparently it isn't supported?)

MarkMLl

  • Hero Member
  • *****
  • Posts: 6686
Re: Trying to bind a C library
« Reply #10 on: March 22, 2021, 07:46:03 pm »
Quote
The perils of people not posting the exact code that was giving them problems...
Yes, I am sorry, I thought it would be more straight forward with "dumbed down" c code.

No problem :-)

Quote
I tried multiple settings to compile the Wren library, but I still get the errors. I wanted to make sure that I can load .dll that have been built with VS (I also tried to load a .lib but apparently it isn't supported?)

The ultimate arbiter will be looking at the machine code associated with the specific entry and return points in the DLL. But I admit that I'm extremely rusty at this sort of thing... I've not had to do it for 20+ years and the available tools have changed a lot since then.

What do you mean that .lib isn't supported? Do you mean that the library you're trying to load isn't available in a .lib for static linkage or that FPC can't do static linkage (the latter is definitely wrong).

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

lumi

  • New Member
  • *
  • Posts: 17
Re: Trying to bind a C library
« Reply #11 on: March 22, 2021, 08:18:41 pm »
Quote
What do you mean that .lib isn't supported? Do you mean that the library you're trying to load isn't available in a .lib for static linkage or that FPC can't do static linkage (the latter is definitely wrong).

What I meant was, that I tried following the binding guide (https://github.com/williamhunter/pascal-bindings-for-c) and added
Code: Pascal  [Select][+][-]
  1. {$linklib wren.lib}
at the top of my binding and I got a compile error :
Code: [Select]
Invalid DLL, Dos Header invalid

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Trying to bind a C library
« Reply #12 on: March 22, 2021, 08:23:25 pm »
if you're using Borland C or MSVC it might not work.
You want to use gcc compiler instead. or maybe even clang.

Gcc from mingw package is the usual choice.

Please note that LINKLIB is used for STATIC linking.

If you're compiling a .dll, then any C/C++ compiler would work, but you should not be using $linklib.
Instead you should declare a function as external and specify the dll name in the external reference.
« Last Edit: March 22, 2021, 08:28:45 pm by skalogryz »

lumi

  • New Member
  • *
  • Posts: 17
Re: Trying to bind a C library
« Reply #13 on: March 22, 2021, 09:25:25 pm »
Let me rephrase cause I might be expressing myself poorly.
I first tried to dynamically link the .dll (compiled with msvc) with external references.
And then I tried to statically link it with a .lib with $linklib  that I compiled using MSVC.

Both failed with different error messages, probably cause I messed up somewhere!

I'm gonna leave the source too so it's easier to spot the mistakes. (it's not terribly long, but I'm not well versed enough with pascal yet)
Here is what I have currently for the binding(dynamic linking): https://gist.github.com/lumi-c/0a84df98685460d43c281fa508e86b25
And here is the header of the source code: https://github.com/wren-lang/wren/blob/main/src/include/wren.h

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Trying to bind a C library
« Reply #14 on: March 22, 2021, 09:44:34 pm »
And then I tried to statically link it with a .lib with $linklib  that I compiled using MSVC.
Static linking with MSVC out-of-thebox compiled librariry won't work.
Maybe there are some settings in MSVC to compile gcc compatible libraries, but I doubt.
So let's forget this option

tried to dynamically link the .dll (compiled with msvc) with external references.
...
different error messages, probably cause I messed up somewhere!
what compilation error did you get when tied to use the .dll?

 

TinyPortal © 2005-2018