简体   繁体   中英

Can I store pointers to C++ classes in C?

How do I store a pointer to a C++ class in a C struct?

I'm working with an API where the basic unit of storage is a C struct (MaxMSP). I'd like to use C++. I've attempted to store a pointer to my class in a void* but deleting it (in C++) causes a crash

extern "C" void* MyClass_New(){
     MyClass* temp = new MyClass();
     return (void*)temp;
}

extern "C" void MyClass_Delete(void* myclass){
      delete (MyClass*)myclass;  //<--- this line crashes.
}

I'm aware this is ugly and dangerous but I don't see another way to do this. do you?

I expected a void* would adequately keep track of a C++ class but calling delete after casting said void* causes a crash.

/////// Here's my minimal reproducible.

.c:

int main(int argc, const char * argv[]) {

    void* temp;
    temp= MyClassTranslator_New(4);   
    MyClassTranslator_Kill(temp);


    return 0;
}

.hpp

#ifndef m2ot_base_hpp
#define m2ot_base_hpp


#if defined __cplusplus



extern "C" class MyClassTranslator
{

    private :
        long num;

    public:
        MyClassTranslator(const long num);
        ~MyClassTranslator(){;};
        MyClassTranslator( const MyClassTranslator &obj);


        long getNum(void){return this->num;};


};

extern "C"  void* MyClassTranslator_New(const long num);

extern "C"  void MyClassTranslator_Kill(void* thisc);


#endif

#endif /* m2ot_base_hpp */

.cpp



MyClassTranslator::MyClassTranslator( const MyClassTranslator &that){
    this->num=that.num;
}

extern "C"  void* MyClassTranslator_New(const long num)
{
    MyClassTranslator* temp= new MyClassTranslator(num);

    return static_cast<void*> (temp);
}

extern "C"  void MyClassTranslator_Kill(void* thisc){
    delete static_cast<MyClassTranslator*>(thisc);
}


MyClassTranslator::MyClassTranslator(const long num){
    this->num=num;
}

Can I store pointers to C++ classes in C?

Yes.

but deleting it (in C++) causes a crash

There are a few possibilities:

  • You passed a pointer to MyClass_Delete that didn't originate from MyClass_New .
  • You passed the same pointer to MyClass_Delete more than once.
  • The destructor of the class crashes.

Regarding style:

The cast in MyClass_New is redundant.

I recommend not using C style cast in C++. You can use static_cast to convert from void* .

You could use a wrapper such as:

struct MyClass_handle {
    void* ptr;
};
struct MyClass_handle MyClass_New();
void MyClass_Delete(struct MyClass_handle myclass);

The use of typed handle makes it easier to catch incorrect usage.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM