C++ DLL to be used in C program

2019-07-16 11:42发布

I have a dll whose source code is written in C++ . I would like to create the static version of that library and I would like to be able to link this static library in a another library which is written in pure C. The compiler is MinGW on Windows. How should I compile the first C++ static library so to make it usable by a C library?

标签: c++ c dll mingw
3条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-07-16 12:11

You don't, you do the opposite. You make the C library work in your C++ program. C++ encompasses C, not the other way around (superset C++, subset C). So what you do, is you can write a C++ program (using C++ or C syntax), and compile this program with a c++ compiler. You can then use C and C++ libraries.

查看更多
叛逆
3楼-- · 2019-07-16 12:11

You add a C API to your C++ library. In the header file you add

#ifdef __cplusplus
extern "C" {
#endif
.
.
.
#ifdef __cplusplus
}
#endif

You do the same in your C api C++ file "but you can leave out the #ifdefs because you know you will be compiling them using your C++ compiler.

You C api C++ file then can access the C++ API but your library is guaranteed to export using the C style Application Binary interface (no name mangling). The library can then be used from a C application.

The header file will be good to go both in C and C++ projects

查看更多
唯我独甜
4楼-- · 2019-07-16 12:22

If you plan on calling member functions of an instance of C++ class you will need to provide forwarding functions. You will also need to provide at least one function to return a pointer to an instance of the class you want to access. There are to significant reasons for this. 1) Constructors are special and do not have names so they cannot be called directly and 2) member functions take an implicit this parameter which can be passed on the stack or in a register.

For instance let's say you have a class called SomeClass

#include <iostream>

class SomeClass
{
public:
    void Print(int value) { std::cout << value << std::endl; }
    void Print(const char *value) { std::cout << value << std::endl; }
};

Now, you want to add a type safe way of creating and accessing an instance of that class. You can create a C interface that provides the creation function and forwarding functions. You might start by adding an additional header file to provide the C interface for SomeClass

XSomeClass.h

#ifdef __cplusplus
extern "C"
{
#endif

    // C type representing SomeClass. This adds some type safety to it's use in C    
    typedef struct XSomeClass XSomeClass;

    // This will create an instance of SomeClass and return a pointer to XSomeClass
    XSomeClass* SomeClass_Create( );

    // forwarding calls to access member functions of SomeClass. These calls take
    // an explicit pointer to XSomeClass as the first parameter. self points to
    // an instance of SomeClass returned by SomeClass_Create()
    void SomeClass_PrintInt(XSomeClass* self, int value);
    void SomeClass_PrintString(XSomeClass* self, const char *value);

#ifdef __cplusplus
}
#endif

Now you need to provide an implementation of the C interface. This is where all the magic happens that allows you to call C++ member functions from C.

XSomeClass.cpp

extern "C" XSomeClass* SomeClass_Create()
{
    return reinterpret_cast<XSomeClass*>(new SomeClass());
}

extern "C" void SomeClass_PrintInt(XSomeClass* self, int value)
{
    reinterpret_cast<SomeClass*>(self)->Print(value);
}

extern "C" void SomeClass_PrintString(XSomeClass* self, const char *value)
{
    reinterpret_cast<SomeClass*>(self)->Print(value);
}

I recommend using reinterpret_cast over C style casts to prevent the accidental removal of const qualifiers.

To access the C++ library from C you can now do something like the example below

main.c

#include "XSomeClass.h"

int main(int, char**)
{
    XSomeClass *sc = SomeClass_Create();
    SomeClass_PrintInt(sc, 1);
    SomeClass_PrintString(sc, "hello");
}



Note: Simply putting the C++ library in a DLL and calling GetProcAddress for free functions and static member functions will be difficult as you will need to take into account name mangling.

查看更多
登录 后发表回答