【发布时间】:2012-07-12 13:39:45
【问题描述】:
在 Ada95 中使用 C++ 类/构造函数和受控类型
我希望能够在我的 Ada 代码中使用 C++ 类。我的目标是保持我的 Ada 代码可移植到 Ada95 规范。我不想使用任何 GNAT 或 Ada05 特定方法。
我在 C 中使用带有包装函数的编译指示导入 (C) 来实现我的 接口。但我无法弄清楚如何获得我的 C++ Ctors/Dtors 自动调用。我的第一个想法是使用 Ada Controlled Types Initialize 会调用Ctor,Finalize 会调用Dtor。这 在我有一个需要我传递参数的 Ctor 之前,一切都很好。
Foo.h
class Foo
{
public:
Foo();
Foo(long x, long y, long z);
Foo(const Foo& that);
~Foo();
Foo& operator=(const Foo& that);
long getX() const;
long getY() const;
long getZ() const;
void setX(long x);
void setY(long y);
void setZ(long z);
private:
long mX;
long mY;
long mZ;
};
Foo_Exports.cpp
#include "foo.h"
#include <new>
extern "C"
{
void extFoo_New (Foo* foo) { new (foo) Foo(); }
void extFoo_NewXYZ (Foo* foo, long x, long y, long z) { new (foo) Foo(x,y,z); }
void extFoo_Delete (Foo* foo) { foo->~Foo(); }
long extFoo_getX(const Foo& foo) { return foo.getX(); }
long extFoo_getY(const Foo& foo) { return foo.getY(); }
long extFoo_getZ(const Foo& foo) { return foo.getZ(); }
void extFoo_setX(const Foo& foo, long x) { foo.setX(x) };
void extFoo_setY(const Foo& foo, long y) { foo.setY(y) };
void extFoo_setZ(const Foo& foo, long z) { foo.setZ(z) };
}
cpp.foo.ads
with Ada.Finalization;
with Interfaces.C;
use Interfaces.C;
package Cpp.Foo is
type Obj_t is new Ada.Finalization.Controlled_Type with private;
procedure Initialize (This : in out Obj_T);
procedure Adjust (This : in out Obj_T);
procedure Finalize (This : in out Obj_T);
function Get_X (This : access Obj_T) return Long;
function Get_Y (This : access Obj_T) return Long;
function Get_Z (This : access Obj_T) return Long;
procedure Set_X(This : access Obj_T;
X : in Long );
procedure Set_Y(This : access Obj_T;
Y : in Long );
procedure Set_Z(This : access Obj_T;
Z : in Long );
private
type Obj_t is new Ada.Finalization.Controlled_Type with null record;
for Obj_T'Size use 192;
for Obj_T'Alignment use 8;
pragma Import (C, Get_X, "extFoo_getX");
pragma Import (C, Get_Y, "extFoo_getY");
pragma Import (C, Get_Z, "extFoo_getZ");
pragma Import (C, Set_X, "extFoo_setX");
pragma Import (C, Set_Y, "extFoo_setY");
pragma Import (C, Set_Z, "extFoo_setZ");
end Cpp.Foo;
cpp.foo.adb
with System;
package body Cpp.Foo is
procedure Initialize (This : in out Obj_T) is
procedure ExtFoo_New(Addr : in System.Address);
pragma Import (C, ExtFoo_New "extFoo_New");
procedure ExtFoo_NewXYZ(Addr : in System.Address,
X : in Long;
Y : in Long;
Z : in Long);
pragma Import (C, ExtFoo_NewXYZ "extFoo_NewXYZ");
begin
null; -- **WHAT DO I DO HERE?!**
end Initialize;
procedure Adjust (This : in out Obj_T) is
begin
null; -- TBD copy ctor
end Adjust;
procedure Finalize (This : in out Obj_T) is
procedure ExtFoo_Delete(Addr : in System.Address);
pragma Import (C, ExtFoo_Delete, extFoo_Delete);
begin
ExtFoo_Delete(This'address);
end Finalize;
end Cpp.Foo;
【问题讨论】:
-
Obj_t 需要保留一些 C++ 构造函数的返回值的记录(你为什么要指定'Size 和'Alignment?);我不相信你可以欺骗 Ada 和 C(++) 让两者使用相同的内存区域。 Initialize 仅在默认初始化时调用,并且会调用 ExtFoo_New。你需要另一个 Ada 子程序(函数,我希望)来调用 ExtFoo_NewXYZ。
-
@SimonWright 我正在使用“大小”和“对齐”,以便在声明新的 Obj_T 时可以在堆栈上分配正确数量的数据。您可以通过使用 'Address [for Obj'Address use addr;] 的表示子句来欺骗 Ada 使用 C++ 内存,并且您可以使用 Placement new 语法 [Foo* foo = new (addr) Foo() 在 C++ 中做同样的事情;]。 -- 如果我创建另一个子程序来调用 ExtFoo_NewXYZ,我如何让它被自动调用?我希望我的 Ada 接口看起来像 Ada 代码,而不是 C++ 代码的 Ada 接口。
-
@Jerunh:使用 Swig (swig.org) 怎么样?
-
@wilx 根据 Swig 网页,Ada 没有被列为兼容语言。
-
@Jerunh:啊,对不起。我确信它就在那里。
标签: c++ constructor ada