How to call a C++ constructor from a C-File

前端 未结 1 1704
没有蜡笔的小新
没有蜡笔的小新 2021-02-05 09:32

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 par

1条回答
  •  失恋的感觉
    2021-02-05 10:34

    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(new MyType);
       }
       catch (...) {
         return nullptr;
       }
     }
    
     EXTERNC mylibraryname_mytype_t create_mytype_with_int(int val) NOTHROW {
       try {
         return static_cast(new MyType(val));
       }
       catch (...) {
           return nullptr;
       }
     }
    
     EXTERNC void mylibraryname_free_mytype(mylibraryname_mytype_t obj) NOTHROW {
       try {
         MyType* typed_obj = static_cast(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.

    0 讨论(0)
提交回复
热议问题