c++c

How to create a new object in a c function and pass a reference to it?


The essence of my question is this:

What is the best approach for creating a new object in a c function and pass some reference to that new object to the caller?

My overall setting is a bit more complex and involves mixed c and c++ code, so I am including some background information:

I am creating a c++ library for a 3D engine. The library is intended to be used from host applications on different platforms.

For easy compatibility reasons I now intent to hide all c++ code behind an API in plain c. This works pretty well so far.

The only thing I am not sure about is, which is the best way for actually creating my engine instance through my c API.

My first approach was this:

// in myEngineAPI.h
void myEngineCreate(void * myEngine);
void myEngineRelease(void * myEngine);


// in myEngineAPI.cpp
#include "myEngineAPI.h"
#include "myPrivateCppEngine.h"

void myEngineCreate(void * myEngine) {
    myEngine = new Engine;               // <- this doesn't seem to work as expected
}
void myEngineRelease(void * myEngine) {
    delete ((Engine *)myEngine);
}


// in my host application
#include "myEngineAPI.h"

void * myEngine = NULL;
myEngineCreate(myEngine);    // <- problem: myEngine is still NULL after this line.

// ...draw some fancy stuff...

myEngineRelease(myEngine);

I would expect that myEngineCreate(void * myEngine) would assign the address of my newly created object to myEngine. But after the function returns, myEngine still points to NULL. Why?

Now my second approach was this:

// in myEngineAPI.h
void * myEngineCreate();
void myEngineRelease(void * myEngine);


// in myEngineAPI.cpp
#include "myEngineAPI.h"
#include "myPrivateCppEngine.h"

void * myEngineCreate() {
    return new Engine;               // <- ok, the function returns a valid pointer
}
void myEngineRelease(void * myEngine) {
    delete ((Engine *)myEngine);
}


// in my host application
#include "myEngineAPI.h"

void * myEngine = myEngineCreate();  // <- yay, I have a void pointer to my engine

// ...draw some fancy stuff...

myEngineRelease(myEngine);

This works. myEngineCreate() gives me an opaque pointer to my engine instance, which I can use in my subsequent drawing calls and which I can also hand to my release function that cleans up memory when I'm done with it. The problem with this approach is, that my profiler complains about a memory leak in myEngineCreate(). I understand that creating an object in one place and owning it in another is a delicate business, and I seem to do something wrong here - but what?

Thanks in advance for any advice or help.


Solution

  • Lets take your myEngineCreate function:

    void myEngineCreate(void * myEngine) {
        myEngine = new Engine;
    }
    

    This does not work because myEngine is a local variable within the scope of the myEngineCreate function. To pass a pointer "by reference" in C you have to pass it as a pointer to a pointer, and use the derefernece operator to assign to the pointer:

    void myEngineCreate(void ** myEngine) {
        *reinterpret_cast<Engine**>(myEngine) = new Engine;
    }
    

    And you call it by using the address-of operator & of a pointer:

    void * myEngine;
    myEngineCreate(&myEngine);
    

    As a late addendum, another possible solution is to return the new pointer:

    void* myEngineCreate() {
        return reinterpret_cast<void*>(new Engine);
    }