C++ 如何在c函数中创建新对象并向其传递引用?
我的问题的实质是: 在c函数中创建新对象并将对该新对象的引用传递给调用方的最佳方法是什么 <>强>我的总体设置有点复杂,涉及到C和C++代码的混合,所以我包含了一些背景信息:>/P> 我正在为3D引擎创建一个C++库。 该库用于不同平台上的主机应用程序 <> P>为了便于兼容性,我现在打算在C中隐藏所有的C++代码。 到目前为止,这种方法效果很好 我唯一不确定的是,这是通过我的c API实际创建引擎实例的最佳方法 我的第一个方法是:C++ 如何在c函数中创建新对象并向其传递引用?,c++,c,C++,C,我的问题的实质是: 在c函数中创建新对象并将对该新对象的引用传递给调用方的最佳方法是什么 强>我的总体设置有点复杂,涉及到C和C++代码的混合,所以我包含了一些背景信息:>/P> 我正在为3D引擎创建一个C++库。 该库用于不同平台上的主机应用程序 P>为了便于兼容性,我现在打算在C中隐藏所有的C++代码。 到目前为止,这种方法效果很好 我唯一不确定的是,这是通过我的c API实际创建引擎实例的最佳方法 我的第一个方法是: // in myEngineAPI.h void myEngineCr
// 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);
// 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;
}
这不起作用,因为myEngine
是myEngineCreate
函数范围内的局部变量。要在C中“通过引用”传递指针,必须将其作为指向指针的指针传递,并使用derefernece运算符指定给指针:
void myEngineCreate(void ** myEngine) {
*reinterpret_cast<Engine**>(myEngine) = new Engine;
}
作为最新的附录,另一种可能的解决方案是返回新指针:
void* myEngineCreate() {
retur reinterpret_cast<void*>(new Engine);
}
void*myEngineCreate(){
重新解释铸件(新发动机);
}
我使用不透明指针做了类似的事情:
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;
}
}
typedef struct my_c_engine*myengine;
外部“C”myEngine createEngine(){
返回reinterpret_cast(新的myRealEngineClass());
}
外部“C”无效释放引擎(MyEngine C){
如果(c){
myRealEngineClass*x=重新解释(c);
删除x;
}
}
我这样做是因为我希望C部分被完全隔离
在c函数中创建新对象并将对该新对象的引用传递给调用方的最佳方法是什么
在C语言中,面向对象的最佳方法是创建一个不可压缩类型的对象,也称为不透明类型(空指针不是不透明类型,它只是一个原始地址)
例如:
//引擎
typedef struct engine_t engine_t;
engine_t* engine_create (void);
//引擎c
struct engine_t
{
/* all variables placed here will have true private encapsulation */
};
engine_t* engine_create (void)
{
return malloc(sizeof(engine_t));
}
//main.c
int main()
{
engine_t* my_engine = engine_create();
}
这是C中的真实对象定位,最好是不用C++语言支持的OO。调用方将无法访问结构的任何成员
但是在函数返回后,myEngine仍然指向NULL。为什么?因为指针本身在C和C++中通过值传递。您要么传递指针的地址,要么将指针返回给调用者。关于这个主题的多个问题和常见问题可以在./p>中找到。如果需要使用泛型,在C++中使用<代码>模板<代码>,但尽可能避免<代码>空洞*>代码>!这是容易出错的。我假设主机应用程序是用C和MyEngin在C++中编写的,因此使用Value*,只要你不忘记调用MyEngEnEnLeLeEe(),第二个方法就不应该是个问题,因为第一种方法可以看到下面的Joachim Pileborg的答案(当然,你仍然需要在某个时间点删除对象)。虽然这个答案很好地解释了当前代码不起作用的原因,但请注意,这不是C中的最佳解决方案,因为没有类型安全性。谢谢你指出这一点。我仍然有内存泄漏,我会运行更多的测试…好的,我修复了我的泄漏。我不想把指针语法隐藏在typedef后面,因为读起来很混乱。还有一个附带说明:无论您使用new/delete还是malloc()/free(),都不需要检查
c
是否为NULL。delete和free()都允许NULL作为参数。感谢您在示例中添加extern“C”
。我也不得不把这个添加到我的代码中。你的答案是最详细的,并且给出了很多有趣的细节。尽管如此,到目前为止,我仍然坚持这一观点。这似乎是最简单的解决方案,我现在真的不需要更多。感谢您指出空指针和不透明类型之间的区别。
int main()
{
engine_t* my_engine = engine_create();
}