如何在c函数中创建一个新对象并传递对它的引用

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

本文关键字:对象 引用 新对象 一个 函数 创建      更新时间:2023-10-16

我的问题的实质是:

在c函数中创建一个新对象并将对该新对象的引用传递给调用者的最佳方法是什么?

我的整体设置有点复杂,涉及混合c和c++代码,所以我包括一些背景信息:

我正在为3D引擎创建一个c++库。该库旨在从不同平台的主机应用程序中使用。

为了便于兼容,我现在打算将所有c++代码隐藏在纯c的API后面。

我唯一不确定的是,这是最好的方式实际上创建我的引擎实例通过我的c API。

我的第一个方法是:

// 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);

我希望myEngineCreate(void * myEngine)将我新创建的对象的地址分配给myEngine。但是在函数返回后,myEngine仍然指向NULL。为什么?

现在我的第二个方法是:

// 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);

这工作。myEngineCreate()给了我一个不透明的指针指向我的引擎实例,我可以在我随后的绘图调用中使用,我也可以交给我的释放函数,当我用它完成时清理内存。这种方法的问题是,我的分析器抱怨myEngineCreate()中的内存泄漏。我明白,在一个地方创造一个对象,在另一个地方拥有它是一件微妙的事情,我在这里似乎做错了什么——但是什么?

提前感谢您的建议和帮助

myEngineCreate函数为例:

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

这不起作用,因为myEnginemyEngineCreate函数范围内的局部变量。通过引用传递一个指针在C语言中,你必须把它作为一个指针传递给另一个指针,然后使用解引用操作符给指针赋值:

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

通过使用指针的地址操作符&来调用它:

void * myEngine;
myEngineCreate(&myEngine);

作为最后的补充,另一个可能的解决方案是返回新指针:

void* myEngineCreate() {
    retur reinterpret_cast<void*>(new Engine);
}
在c函数中创建一个新对象并将对该新对象的引用传递给调用者的最佳方法是什么?
在C语言中,最好的面向对象的方法是创建一个不复杂类型的对象,也称为不透明类型(void指针不是不透明类型,它只是一个原始地址)。

的例子://engine.h

typedef struct engine_t engine_t;
engine_t* engine_create (void);
//engine.c

struct engine_t
{
  /* all variables placed here will have true private encapsulation */
};

engine_t* engine_create (void)
{
  return malloc(sizeof(engine_t));
}
//c

int main()
{
  engine_t* my_engine = engine_create();
}

这是C语言中真正的面向对象,在没有c++语言支持的情况下可以实现的最佳OO。调用方将无法访问该结构体的任何成员。

但是函数返回后,myEngine仍然指向NULL。为什么?

因为指针本身在C和c++中是按值传递的。你要么传递指针的地址,要么将指针返回给调用者。关于这个主题的许多问题和常见问题可以在SO.

找到。

我使用不透明指针做了类似的事情:

typedef struct my_c_engine *myCEngine;
extern "C" myCEngine createEngine() {
    return reinterpret_cast<myCEngine>(new myRealEngineClass());
}
extern "C" void releaseEngine(myCEngine c) {
    if(c) {
        myRealEngineClass *x = reinterpret_cast<myRealEngineClass*>(c);
        delete x;
    }
}

我这样做是因为我想让C部分完全隔离。