<style> .reveal { font-size: 32px; } </style> # Talking C++ with Other Languages ### <small>someone get gcc on Duolingo</small> <!-- Put the link to this slide here so people can follow --> slides: https://hackmd.io/@sagnikb/HyyuYhA2o code: [will add after talk] --- ## `static` and `extern` --- ## What does it take? <ul> <li>C++ programs turn into machine code at the end of the day<!-- .element: class="fragment" data-fragment-index="1" --></li> <li>Simply <code>jump</code> to or <code>call</code> to other machine code?<!-- .element: class="fragment" data-fragment-index="2" --></li> <li>How are arguments and return values passed?<!-- .element: class="fragment" data-fragment-index="3" --></li> <li>How is memory managed?<!-- .element: class="fragment" data-fragment-index="4" --></li> <li>And <em>where</em> to jump to?<!-- .element: class="fragment" data-fragment-index="5" --></li> </ul> ---- --- ## Calling C code from C++ ```c /* In Library.h */ const char* getHelloWorld(void); ``` ```c /* In Library.c */ const char* getHelloWorld() { return "Hello world"; } ``` ```cpp /* In Main.cpp */ #include "Library.h" int main() { std::cout << getHelloWorld() << std::endl; } ``` <span> ```shell $ g++ -O3 Library.c Main.cpp -o Main ``` <!-- .element: class="fragment" data-fragment-index="1" --></span> ---- `extern "C"` Linkage ```c [2,4] /* In Library.h */ extern "C" { const char* getHelloWorld(void); } ``` ```c [1] /* In Library.c */ const char* getHelloWorld() { return "Hello world"; } ``` ```cpp [1] /* In Main.cpp */ #include "Library.h" int main() { std::cout << getHelloWorld() << std::endl; } ``` ```shell $ g++ -O3 Library.c Main.cpp -o MainWithExtern ``` <span>What's the difference between `Main` and `MainWithExtern`? <!-- .element: class="fragment" data-fragment-index="1" --></span> ---- Excerpt of `int main()` in `objdump -M intel -D MainWithExtern` ```x86asm ... call 401070 <_ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l@plt> call 401270 <getHelloWorld> ... ``` <span>Excerpt of<!-- .element: class="fragment" data-fragment-index="1" --></span><code>int main()</code><!-- .element: class="fragment" data-fragment-index="1" --> in<!-- .element: class="fragment" data-fragment-index="1" --> <code>objdump -M intel -D Main</code><!-- .element: class="fragment" data-fragment-index="1" --> <span> ```x86asm ... call 401070 <_ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l@plt> call 401270 <_Z13getHelloWorldv> ... ``` <!-- .element: class="fragment" data-fragment-index="1" --></span> Note: Mangling. Function overloading in C++ necessitates name mangling. No overloading in C, no mangling in C. C does not know how to interpret a mangled C++ name, so `extern "C"` linkage makes the names not mangled. It's a contract between the compiler and the linker: the compiler will not produce mangled names, and the linker will find the non-mangled names. ---- A more realistic example of building this: ```makefile all: c cpp c: Library.o gcc -o MainC Library.o Main.c cpp: Library.o g++ -o MainCpp Library.o Main.cpp Library.o: Library.c gcc -c Library.c -o Library.o ``` ---- In order to make header code compatible between C and C++, it is best practice to ```c /* In Library.h */ #ifdef __cplusplus extern "C" { #endif const char* getHelloWorld(void); #ifdef __cplusplus } #endif ``` <span>When `#include`d in a C file, there's no `extern "C"`, but it is present when `#include`d in a C++ file.<!-- .element: class="fragment" data-fragment-index="1" --></span> --- ## Calling C++ Code from C What could go wrong? <ul> <li>Overloaded functions<!-- .element: class="fragment" data-fragment-index="1" --></li> <li>Class layout<!-- .element: class="fragment" data-fragment-index="2" --></li> <li>Methods that take <code>this</code> as a parameter<!-- .element: class="fragment" data-fragment-index="3" --></li> <li>Templates 😍<!-- .element: class="fragment" data-fragment-index="4" --></li> <li>Exceptions, stack unwinding 😍<!-- .element: class="fragment" data-fragment-index="5" --></li> </ul> Note: Boils down to de-sugaring these constructs into ones that fit within the C language. ---- ### Overloaded Functions ```cpp /* In Library.hpp */ int doWork(); int doWork(double aArg); extern "C" { int doWork_void() { return doWork(); }; int doWork_double(double aArg) { return doWork(aArg); }; } ``` Write glue code which can be `#include`d in a C file: ```c /* In LibraryGlue.h */ int doWork_void(void); int doWork_double(double aArg); ``` ---- ### C++ Classes - Create opaque type exposed to C - Generally a bad idea to access class members directly - Be wary of conversions to base class pointers ---- ---- ### Templates - Instantiate templates manually into `extern "C"` functions - Call those functions from C code
{"metaMigratedAt":"2023-06-17T20:02:15.560Z","metaMigratedFrom":"YAML","title":"Talking C++ with Other Languages","breaks":true,"slideOptions":"{\"theme\":\"white\"}","contributors":"[{\"id\":\"bbc52c18-9822-4f81-8d84-cd68fe70b8e2\",\"add\":7535,\"del\":2362}]","description":"slides: https://hackmd.io/@sagnikb/HyyuYhA2o"}
    136 views