How to wrap c++ std::shared_ptr in wrapper headerfile so it can be called from c?

一世执手 提交于 2019-12-25 01:53:40

问题


I'm writing a small Wrapper API so i can call some C++ code (classes/ functions) from C. I got the problem, that one of my C++ functions is initialised in my wrapper header with a "shared_ptr".

ClassName *ClassName _new(std::shared_ptr<Lib::Instance> p_Instance);

So as you can see, the wrapper file is infested with C++ style. This is bad because the Wrapper file should be readable by C AND C++.

This is my Wrapper.h file:

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

typedef struct ClassName ClassName;

ClassName *ClassName_new(std::shared_ptr<Lib::Instance> p_Instance);

void ClassName_setValue(ClassName* t, double p_value);

void ClassName_delete(ClassName* t);

#ifdef __cplusplus
}
#endif /* __cplusplus */

and this is my Wrapper.cpp file:

#include "Wrapper.h"
#include "ClassName.h"

extern "C"{

ClassName* ClassName_new(std::shared_ptr<Lib::Instance> p_Instance){
       return new ClassName(p_Instance);
}

void ClassName_setValue(ClassName* t, double p_value){
        t->setValue(p_value);
}

void ClassName_delete(ClassName* t){
        delete t;
}
}

And this is the part of my main .cpp file Header:

class ClassName: public Lib::Util::Task {
public:
   ClassName(std::shared_ptr<Lib::Instance> p_Instance);
   virtual ~ClassName();
   void setValue(double p_value);
   ...

.Cpp:

ClassName::ClassName(std::shared_ptr<Lib::Instance> p_Instance) ...
...
   void ClassName::setValue(double p_value){
      doSomething()
   }
...

I'm not allowed to change my structure of the main c++ file where I am using the ClassName(std::shared_ptr<Lib::Instance> p_Instance);

Do you have any ideas how I can fix this problem? Maybe writing a second Wrapper?

Edit: Here is the error given by the Terminal:

Wrapper.h:21:45: error: expected ‘)’ before ‘:’ token
 ClassName *ClassName_new(std::shared_ptr<Lib::Instance> p_Instance);
                             ^

回答1:


The function cannot be used in C, so you can use the pre-processor to remove the declaration just like you used with extern "C":

// Wrapper.h
#ifdef __cplusplus
ClassName *ClassName_new(std::shared_ptr<Lib::Instance> p_Instance);
#endif

Although, it this wrapper isn't supposed to be used in C++ by anything other than Wrapper.cpp, then moving the declaration into Wrapper.cpp might be a better option.


If you need a way of invoking ClassName_new from C, I would suggest steering away from shared pointer. But you could make it work with an opaque wrapper:

// Wrapper.h
struct opaque_wrapper* make_instance(void);
void release_instance(struct opaque_wrapper*);
ClassName *ClassName_new(struct opaque_wrapper*);

// Wrapper.cpp
struct opaque_wrapper {
    std::shared_ptr<Lib::Instance> p_Instance;
};
opaque_wrapper* make_instance() {
    return new opaque_wrapper{std::make_shared<Lib::Instance>()};
}
void release_instance(struct opaque_wrapper* instance) {
    delete instance;
}
ClassName *ClassName_new(struct opaque_wrapper* instance) {
    return ClassName_new(instance->p_Instance);
}



回答2:


I would suggest embedding the reference counter into the object and use boost::intrusive_ptr with it. This way you can pass a plain pointer to C functions and those C functions can still manage the object's lifetime directly calling C-style addref/release on it.




回答3:


You cannot use classes from C++ in C.

You can define function prototypes of C calling convention C functions, to be used from C++ with the following wrapper code around in the header file:

#ifdef __cplusplus
extern "C" {
#endif

/* put here C calling convention C functions */

#ifdef __cplusplus
};
#endif

and you'll get a definitions file that can be used either in C or in C++. __cplusplus is a macro defined by the c++ compiler when compiling C++ code, and it introduces the extern "C" { environment to support C functions. Those functions follow the C style calling conventions (you cannot overload them, you cannot use method definitions or define classes in there)



来源:https://stackoverflow.com/questions/58080505/how-to-wrap-c-stdshared-ptr-in-wrapper-headerfile-so-it-can-be-called-from-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!