I didn’t think this could deserve a post, but a friend of mine asked me about how to wrap a C++ class in Fortran, which means wrapping it in C.
I thought of one obvious way, but there is also a typesafe version that should be used.
The simple way
The simple way consists of a simple void* interface:
#ifndef INTERFACE_H #define INTERFACE_H #ifdef __cplusplus extern "C" { #endif void* create_manager(); void destroy_manager(void* manager); void print_manager(void* manager); #ifdef __cplusplus } #endif #endif
The associated implementation is thus:
#include "manager.h" #include "interface.h" void* create_manager() { return reinterpret_cast<void*>(new Manager); } void destroy_manager(void* manager) { delete reinterpret_cast<Manager*>(manager); } void print_manager(void* manager) { reinterpret_cast<Manager*>(manager)->print(); }
Simple, easy and not typesafe.
The correct way
In fact, it is possible to keep the type information, without havong to use reinterpret_casts.
#ifndef INTERFACE_H #define INTERFACE_H #ifdef __cplusplus extern "C" { #endif typedef struct Manager Manager; Manager* create_manager(); void destroy_manager(Manager* manager); void print_manager(Manager* manager); #ifdef __cplusplus } #endif #endif
The tric is to declare the type Manager, but without having to expose it to C. As only pointer is needed, a forward declaration is possible, and as we are in C, a typedef is the only needed instruction.
#include "manager.h" #include "interface.h" Manager* create_manager() { return new Manager; } void destroy_manager(Manager* manager) { delete manager; } void print_manager(Manager* manager) { manager->print(); }
Of course it is not exception safe, I expect my friend to use Fortran 2003’s class to achieve it.
Thank you so much. Your example is finally working after I found so many code fragments (even high rated content on Stack Overflow) that always threw up errors. Thanks a lot!