2

I have created a C++ program and class, and plan to compile it to a library. I have found several websites explaining how to create and use wrappers to access the C++ class methods.

My environment is IAR EWARM which in my case I need to use standard C. To create class instantiated objects, I am using (or will need to use) operator "new", i.e., for class "scrnDev": bLink1 = new( scrnDev );

I have been searching for information on how to instantiate objects using the "new" operator from a C program, but unable to find how this can be accomplished.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
user10326
  • 31
  • 4
  • C and C++ are **different** languages . C for examples has no `new` operator. It is not clear what you plan. And C also does not support OOP, i.e. instantiation. Please read a C book. – too honest for this site Jun 29 '16 at 17:47
  • And hence the point of my question. Then how do I create a non-dynamically allocated object from C, that is defined in a C++ library? – user10326 Jun 29 '16 at 17:48
  • 1
    You cannot. Write a C++ wrapper instead. – too honest for this site Jun 29 '16 at 17:49
  • @user10326 Why do you assume that you should be able to? They are different languages, after all. – unwind Jun 29 '16 at 17:49
  • 2
    Why don't you provide a C function within your C++ library which creates the object and returns a `void *` to it? This hides the `new` operator to C... – Lukas Thomsen Jun 29 '16 at 17:50
  • 2
    You need to write C++ wrapper functions with C linkage to allow you to `new` and `delete` objects. – Paul R Jun 29 '16 at 17:50
  • 4
    @user10326 _"I have found several websites explaining how to create and use wrappers to access the C++ class methods."_ And these weren't giving you sufficient answers? – πάντα ῥεῖ Jun 29 '16 at 17:50
  • @LukasThomsen: That would still be a C++ function. Just with a C interface. – too honest for this site Jun 29 '16 at 17:50
  • You only can do that if you have a C++ compiler to compile the module containing the class. Since IAR EWARM, as you stated, is C only, what will you use to compile the C++ module? Is it g++? – Fabio Ceconello Jun 29 '16 at 17:51
  • @Olaf: Yes but it'll do the trick... you won't be able to use the object though... – Lukas Thomsen Jun 29 '16 at 17:51
  • You need to take special care that your C++ library is linked to all the required C++ runtime libraries. Also, a C program normally will not run the C++ runtime code, so you may need to link your C program with the C++ compiler if you need C++ runtime behavior (such as global constructors). – jxh Jun 29 '16 at 19:32

1 Answers1

7

The usual way is to create some c++ function that can be called from c and returns a void* handle for the class allocated internally:

extern "C" {
     void* createScrnDev() {
          return new scrnDev(); 
     } 
}

Other functions in this wrapper API would take the handle, and cast it back to the original object instance:

extern "C" {
     void blink(void* scrnDev_) {
          static_cast<scrnDev*>(scrnDev_)->blink(); 
     } 
}

Finally you'll need a destroy() function to call delete properly:

extern "C" {
     void destroyScrnDev(void* scrnDev_) {
          delete static_cast<scrnDev*>(scrnDev_); 
     } 
}

As mentioned in comments you can also use an opaque pointer, that uses a struct declaration used in both languages:

scrnDev.h:

 struct scrnDevHandle;

 scrnDevHandle* createScrnDev();
 void blink(scrnDevHandle* scrnDev_);
 void destroyScrnDev(scrnDevHandle* scrnDev_);

scrnDev.cpp:

class scrnDev : public scrnDevHandle {
public:
    scrnDev() {}
    blink() {
        // ...
    }
};

extern "C" {
     scrnDevHandle * createScrnDev() {
          return new scrnDev(); 
     } 
     void blink(scrnDevHandle* scrnDev_) {
          static_cast<scrnDev*>(scrnDev_)->blink(); 
     } 
     void destroyScrnDev(scrnDevHandle* scrnDev_) {
          delete static_cast<scrnDev*>(scrnDev_); 
     } 
}

You might be interested to read some more details about the extern "C" {} interfacing here

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • Hi, this is helpful, and thanks. In the calling C program, what do I cast the void pointer to, since my C program doesn't know about the class? (sorry if that's a dumb question) – user10326 Jun 29 '16 at 18:02
  • @user10326 For any operations in the c++ class, you provide c API functions that take the handle, as mentioned. I'll add a small example. – πάντα ῥεῖ Jun 29 '16 at 18:04
  • 3
    An opaque structure pointer would probably be a better choice than a simple `void*` - You would at least have *some* type checking. – tofro Jun 29 '16 at 18:06
  • 1
    @tofro How should it look like? `typedef void* scrnDevPtr;`? Or using an empty `struct` as base? – πάντα ῥεῖ Jun 29 '16 at 18:14
  • simply `struct scrnDev; struct scrnDevPtr *ptr;` in the C part. There's nothing more that needs to be known there. The C++ part doesn't need to be knowing anything more as well, as it's `static_cast`ing away the type anyways. – tofro Jun 29 '16 at 18:24
  • All great information, thanks. One further question with respect to overloaded operators. I have a method with overloaded operators, by number and type of variables. Would each of these methods require a static cast as in the example earlier in this post? – user10326 Jun 29 '16 at 18:32
  • @user10326 Yes, the static cast is necessary to access any members of the underlying c++ class. – πάντα ῥεῖ Jun 29 '16 at 18:35
  • Thanks to everyone who took the time to answer! There is adequate information here to help understand and take a try on it. 8) – user10326 Jun 29 '16 at 18:42
  • @user10326 De nada ;-). I've already earned 50 fake internet points of reputation writing that answer. Well, I think your question is useful for future research. – πάντα ῥεῖ Jun 29 '16 at 18:45