在extern“C”中包装C ++对象

时间:2011-05-27 13:39:43

标签: c++ c cross-platform

考虑一个简单的示例类:

class BankAccount {
public:
   BankAccount() { balance =0.0; };
  ~BankAccount() {};
   void deposit(double amount) {
      balance += amount;
   }
   private:
      double balance;
};

现在说我想将它包装在extern“C”中,以便我可以从许多不同的编程语言(如C#和Java)中调用它。 我尝试了以下似乎有效的方法:

// cbankAccount.h:
extern "C" unsigned long createBackAccount(); 
extern "C" void deposit(unsigned long bankAccount, double amount);
// cbankAccount.cpp
unsigned long createBackAccount() {
  BankAccount *b = new BankAccount();
  return (unsigned long) b;
}
void deposit(unsigned long bankAccount, double amount) {
  BankAccount *b = (BankAccount*) bankAccount;
  b->deposit(amount);
} 

这可移植吗? 类型无符号“unsigned long”是否足够大以容纳对象指针? 这种方法还有其他问题吗?

提前感谢您的任何答案!

6 个答案:

答案 0 :(得分:10)

呀。这不好。特别糟糕。 unsigned long - 没有。返回一个正确键入的BankAccount* - 其他语言将在另一端看到它作为通用指针(如System.IntPtr),并且当二进制接口无法输入指针时,无需返回无类型指针

extern "C" BankAccount* CreateBankAccount() {
    return new BankAccount;
}
extern "C" void deposit(BankAccount* account, double amount) {
    account->deposit(amount);
}

答案 1 :(得分:9)

基本上看起来很好用一个附带条件。尝试使用整数类型来保存指针不是一个好主意 - 使用void*要好得多,因为根据定义,它是指针的宽度。


实际上,我认为@ DeadMG的答案比这更清晰。

答案 2 :(得分:5)

强类型甚至比空白*更好。

typedef struct BankAccountProxy *  BankAccountPtr;

BankAccountPtr createBackAccount() {
  BankAccount *b = new BankAccount();
  return (BankAccountPtr) b;
}

答案 3 :(得分:3)

这不可移植,因为unsigned long可能不足以指针。一个不太罕见的平台就是win64。

最好使用ptrdiff_tvoid*

答案 4 :(得分:3)

可能是平台依赖于长度是否足够大(可能不在x86-64上),另一种方法是使用像swig

这样的东西

答案 5 :(得分:2)

我使用void *而不是unsigned long。