Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C header includes C++ Header #1089

Closed
Matthew-w56 opened this issue Apr 15, 2024 · 6 comments
Closed

C header includes C++ Header #1089

Matthew-w56 opened this issue Apr 15, 2024 · 6 comments

Comments

@Matthew-w56
Copy link

Matthew-w56 commented Apr 15, 2024

I am attempting to use the Dart FFIGen to generate a binding for a library written in C++, with C-compatible headers. When I run the FFIGen, I get the following errors:

`PS C:\Users\mbwil\Documents\Programming\Flutter\guido_integration> dart run ffigen -v fine

[INFO] : Running in Directory: 'C:\Users\mbwil\Documents\Programming\Flutter\guido_integration'

[FINE] : Adding header/file: C:\Users\mbwil\Desktop\guidolib\src\engine\include\GUIDOEngine.h

[FINE] : CompilerOpts used: []

[INFO] : Input Headers: [C:\Users\mbwil\Desktop\guidolib\src\engine\include\GUIDOEngine.h]

[FINE] : Creating TranslationUnit for header: C:\Users\mbwil\Desktop\guidolib\src\engine\include\GUIDOEngine.h

[SEVERE] : Header C:\Users\mbwil\Desktop\guidolib\src\engine\include\GUIDOEngine.h: Total errors/warnings: 20.

[SEVERE] : C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.39.33519\include\yvals_core.h:28:2: error: Error in C++ Standard Library usage [User-Defined Issue]

[SEVERE] : C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.39.33519\include\yvals.h:334:1: error: unknown type name 'namespace' [Semantic Issue]

[SEVERE] : C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.39.33519\include\yvals.h:334:1: error: expected ';' after top level declarator [Parse Issue]

[SEVERE] : C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.39.33519\include\cstdlib:22:62: error: expected function body after function declarator [Parse Issue]

[SEVERE] : C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt\corecrt_wstdio.h:34:14: error: unknown type name 'FILE' [Semantic Issue]`

The second error stands out to me as the reason for the cascade of issues. Specifically, the build tools in the visual studio folder are C++ headers, and use the namespace keyword. This causes the tool to fail because C doesn't support this. So what is there to be done to avoid this collision?

Is there something in the internals that needs to be able to deal with C++ headers being depended on within the build tools, or am I missing a way around this problem?

Extra Information:

  • Windows 10
  • Library is GuidoLib (sheet music engraving library)

Thanks for any help!

@dcharkes
Copy link
Collaborator

Just googling around:

https://github.com/microsoft/STL/blob/main/stl/inc/yvals.h#L334C1-L334C11

_STD_BEGIN // equal to namespace mynamespace {

https://stackoverflow.com/questions/41536696/how-where-c-namespace-std-is-defined-link-to-documentation-standard

C doesn't have namespaces.

So the headers are at least not transitively compatible with C.
Maybe it will succeed if you set a filter on what bindings are generated to not generate for the MSVC and Windows includes.

headers:
  entry-points:
    - ...
  include-directives:
    - 'C:\Users\mbwil\Desktop\guidolib\src\engine\include\**'

@Matthew-w56
Copy link
Author

Is there a way to filter like that? This is my configuration and it seems to include what it needs to the in the project without explicitly including those c++ headers.

ffigen:
output: 'lib/guido/generated_bindings.dart'
name: 'GuidoWrapper'
description: 'Guido C Library wrapper for Dart'
ignore-source-errors: true
functions:
expose-typedefs:
include:
- '.*'
headers:
entry-points:
- 'C:/Users/mbwil/Desktop/guidolib/src/engine/include/GUIDOEngine.h'
include-directives:
- 'C:/Users/mbwil/Desktop/guidolib/build/lib/GUIDOEngine64.dll'
- 'C:/Users/mbwil/Desktop/guidolib/build/lib/GUIDOEngine64.exp'
- 'C:/Users/mbwil/Desktop/guidolib/build/lib/GUIDOEngine64.lib'
- 'C:/Users/mbwil/Desktop/guidolib/src/include'
- 'C:/Users/mbwil/Desktop/guidolib/src/engine/include/**'
- 'C:/Users/mbwil/Desktop/guidolib/src/lib'
- 'C:/Users/mbwil/Desktop/guidolib/build'

@dcharkes
Copy link
Collaborator

I'm not familiar with the Windows headers here.

I'd expect the _STD_BEGIN macro to be defined as empty for C compatibility.
If the _STD_BEGIN is unconditionally defined as a namespace, it is not C compatible.

Googling some more:
https://github.com/microsoft/STL
This is the C++ standard library. So it's unsurprising it's incompatible with C.
Are you sure what's in your include-directives is C compatible only?
Maybe try removing things from your include-directives to generate less and try to only generate for the single header file?

ignore-source-errors: true

You might want to remove this to triage errors.

@Matthew-w56
Copy link
Author

Matthew-w56 commented May 11, 2024

So I've been working on it and it is still giving me problems. I cut down to absolutely no includes, and just the entry point, and it still somehow thinks it has to compile the c++ headers that are indirectly linked to. Is there anything that can be done about this? I'm just not aware of what can be done here. Here is my section in the pubspec.yaml:

ffigen:
output: 'lib/guido/generated_bindings.dart'
name: 'GuidoWrapper'
language: c
description: 'Guido C Library wrapper for Dart'
headers:
entry-points:
- 'C:/Users/mbwil/Desktop/guidolib/src/engine/include/GUIDOEngine.h'

Edit:
Where my confusion comes in is that I used this same tool (dart ffigen) to generate bindings for a different c++ library with a C header, and it didn't give me problems. So what could be causing the tool to think it has to go and compile the non-C headers?

@dcharkes
Copy link
Collaborator

Where my confusion comes in is that I used this same tool (dart ffigen) to generate bindings for a different c++ library with a C header, and it didn't give me problems. So what could be causing the tool to think it has to go and compile the non-C headers?

This seems to be the right question to ask.

I cut down to absolutely no includes, and just the entry point, and it still somehow thinks it has to compile the c++ headers that are indirectly linked to.

I guess the next step is to make a copy of C:/Users/mbwil/Desktop/guidolib/src/engine/include/GUIDOEngine.h and start removing stuff from that until it works. If it's an empty file with a single function from your other project it should work.

I'm sorry I can't provide much help here. I'm curious what you'll find!

@Matthew-w56
Copy link
Author

Okay I got it resolved. For any who find this thread with the same or similar issue:

The FFIGen tool attempts to generate the bindings for everything needed for any entry points you give it. So, if your header file makes imports to the rest of your program, it will pull those in, too. This lead to a chain of imports for me, which was a problem because the library itself is written in C++, but all the headers themselves are C-compatible. So, for me, the easiest solution was to create a new header and .cpp file, and create simple driver methods for what I needed to access through the API. The .cpp file was able to import whatever it wanted, as long as the .h file didn't import anything from the rest of the project (or from most of the C++ standard library). Instead, structs and library-defined objects were referred to as void* in the header file, and casted to their appropriate types in the .cpp file.

This way, the FFIGen tool can create bindings for my custom header file (which I got built into my dll), and I can interact with the library through those defined methods.

Thanks all for the suggestions and feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants