I've imported this program, which is parsing a lot of complex text and it's written in C. My own project is written in C++.
I actually intended, that whenever the parser-algorithm has found one of the key-tags then a one (of many) constructor of my class should be called, so that I'll have a nice structure in the end of the txt, as a result of the parsing process.
Here's the problem: I learned OOP with Java and started C++ with this project, so I need a little help: how can I call a C++ constructor out of my C based parser file ? I already checked the internet, but either this question is too trivial or my intended solution is not working ;)
Thanks for any advises.
You can't invoke the constructor, directly, but you can create factory functions that allocate and return instances of your object, and you can write these functions such that the definition is provided in C++ (where it is possible to use "new" to allocate the object and use the C++ constructors) but callable from C.
In the header, you should write:
#ifdef __cplusplus
# define EXTERNC extern "C"
# define NOTHROW noexcept
#else
# define EXTERNC
# define NOTHROW
#endif
/* Alias for your object in C that hides the implementation */
typedef void* mylibraryname_mytype_t;
/* Creates the object using the first constructor */
EXTERNC mylibraryname_mytype_t mylibraryname_create_mytype() NOTHROW;
/* Creates the object using the second constructor */
EXTERNC mylibraryname_mytype_t mylibraryname_create_mytype_with_int(int val) NOTHROW;
/* Frees the object, using delete */
EXTERNC void mylibraryname_free_mytype(mylibraryname_mytype_t obj) NOTHROW;
Then in your C++ source file, you can do:
EXTERNC mylibraryname_mytype_t mylibraryname_create_mytype() NOTHROW {
try {
return static_cast<mylibraryname_mtype_t>(new MyType);
}
catch (...) {
return nullptr;
}
}
EXTERNC mylibraryname_mytype_t create_mytype_with_int(int val) NOTHROW {
try {
return static_cast<mylibraryname_mytype_t>(new MyType(val));
}
catch (...) {
return nullptr;
}
}
EXTERNC void mylibraryname_free_mytype(mylibraryname_mytype_t obj) NOTHROW {
try {
MyType* typed_obj = static_cast<MyType*>(obj);
delete typed_obj;
}
catch (...) {
// Ignore
}
}
Your C code should then be able to include the same header and use the definition from the C++ source file when linked against the generated library.
Note that the code above is swallowing exceptions wholesale. For a real API, you should provide a way of indicating errors to the caller (e.g. by returning the allocated object via an output parameter and returning a status code) rather than merely suppressing them.
Edit
As noted in the comments, "_t" is technically a reserved suffix (though you should be fine if your symbols have a prefix that is unlikely to be used by standard libraries in the future), so just make sure that your symbols include the library name as a prefix. It should also be noted that the typedef, though not required, is intended to make uses of the object more self-documenting than a raw "void*" all over the place.