Embind.. linking C library incompatible with C++ standard?

192 views
Skip to first unread message

Ben Wiley

unread,
Jul 4, 2021, 8:18:37 PM7/4/21
to emscripten-discuss
Apologies if this is less of an embind question and more of a "how does interop work with C and C++" question. I"m a bit inexperienced using them together but in my case I'm trying to use embind, which requires bindings written in C++, and the library I want to link is written in C. When I try to link this library (https://github.com/korginc/volcasample) I get an error about implicit pointer type conversion:

../volcasample/syro/korg_syro_volcasample.c:713:23: error: assigning to 'uint8_t *' (aka 'unsigned char *') from incompatible type 'void *'
                        psms[i].comp_buf = malloc(comp_dest_size + comp_ofs);
                                           ^

I suppose I could convert the library to valid C++ with correct casting but I'm hoping to avoid having to patch the source library in order to link it. Is there another way? A compiler flag to allow implicit pointer type casting or something like that?

Thanks
Ben

Shachar Langbeheim

unread,
Jul 4, 2021, 11:14:26 PM7/4/21
to emscripten-discuss
Looks like you need to use reinterpret_cast ( https://en.cppreference.com/w/cpp/language/reinterpret_cast ).

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/emscripten-discuss/ad71459d-9e32-4c16-bc2d-052f6c310badn%40googlegroups.com.

Floh

unread,
Jul 6, 2021, 6:46:57 AM7/6/21
to emscripten-discuss
This is weird because it looks the .c file is compiled as C++ (not requiring a cast for malloc() is perfectly fine C code, but not valid C++ code).

I would start looking into the build system instead of trying to "C++-ify" the C sources. Somehow the build system seems to treat .c files as C++ (maybe it always calls em++ instead of emcc? emcc should select the right language mode based on the file extension, while em++ forces C++ mode even for .c files.

As a "hack" you can also force compilation in C mode with the "-x c" command line option, for instance:

em++ bla.c -o bla -x c

Ben Wiley

unread,
Jul 7, 2021, 6:45:51 PM7/7/21
to emscripten-discuss
Thanks for taking a look. I must be doing something incorrectly. Here is the article I am trying to follow. Note this section "What about C?" https://developers.google.com/web/updates/2018/08/embind#what_about_c

embind was written for C++ and can only be used in C++ files, but that doesn't mean that you can't link against C files! To mix C and C++, you only need to separate your input files into two groups: One for C and one for C++ files and augment the CLI flags for emcc as follows:

$ emcc --bind -O3 --std=c++11 a_c_file.c another_c_file.c -x c++ your_cpp_file.cpp

I tried doing similar in my case where I replace the ".c" files with the library I'm trying to bind, and I replace the ".cpp" file with my own bindings file.

Perhaps the included command is wrong?

Cheers
Ben

Floh

unread,
Jul 8, 2021, 5:17:21 AM7/8/21
to emscripten-discuss
Hmm, that casting problem in the original code snippet should be unrelated to embind. 

This command line from the article forces all .c files to be compiled as C++ because of the "-x c++" command line option:

emcc --bind -O3 --std=c++11 a_c_file.c another_c_file.c -x c++ your_cpp_file.cpp

So that's the problem. If you drop both the "-std=c++11" and "-x c++" command line options it should work, because then the .c files will be compiled as C and the .cpp files as C++. If you actually need to control the C++ version used via "-std=c++11", then I think you need to invoke emcc twice, once to compile all .c files, and another time to compile all .cpp files (maybe there's another way to do it in one invokation I'm not aware of though).

Cheers!

Floh

unread,
Jul 8, 2021, 5:28:13 AM7/8/21
to emscripten-discuss
Aha! This is actually a case where emcc behaves differently than clang:

In emcc, the argument "-x c++" seems to affect *all* source files, while in clang it only affects source files after the option. For instance (the bla.c file contains an malloc without cast which fails in C++):

emcc bla.c -x c++ blub.cc -o bla

Fails because bla.c is compiled as C++. While in native clang (tested with Apple's clang):

clang bla.c -x c++ blub.cc -o bla

...everything compiles fine, because the "-x c++" only affects the blub.cc file...

And a few more examples to validate the theory:

clang -x c++ blub.cc bla.c -o bla

...fails bcause bla.c is compiled as C++, but:

clang -x c++ blub.cc -x c bla.c -o bla

...works. But this also works in emcc:

emcc -x c++ blub.cc -x c bla.c -o bla

But this does not:

emcc -x c bla.c -x c++ blub.cc -o bla

How weird! :D

(PS: all tested with emcc 2.0.25)

Floh

unread,
Jul 8, 2021, 10:53:15 AM7/8/21
to emscripten-discuss
PPS: the second-last example *doesn't* actually work, because blub.cc is compiled as C (I just didn't notice that because my blub.cc file was also valid C code).

I wrote an emscripten ticket here:

Reply all
Reply to author
Forward
0 new messages