consider a simple example class:
class BankAccount {
public:
BankAccount() { balance =0.0; };
~BankAccount() {};
void deposit(double amount) {
balance += amount;
}
private:
double balance;
};
Now say I want to wrap this in extern "C" so that I can call it from many different programming languages such as C# and Java. I tried the following which seemed to work:
// 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);
}
Is this portable? Is the type unsigned "unsigned long" large enough for an object pointer? Any other problems with this approach?
Thank in advance for any answers!
The C Wrapper provides access to RPC-based components from C applications and enables users to develop both clients and server. This section introduces the various possibilities for RPC-based client applications written in C. Using the C Wrapper in Single-threaded Environments (UNIX, Windows)
By declaring a function with extern "C" , it changes the linkage requirements so that the C++ compiler does not add the extra mangling information to the symbol. This pattern relies on the presence of the __cplusplus definition when using the C++ compiler. If you are using the C compiler, extern "C" is not used.
Not any C-header can be made compatible with C++ by merely wrapping in extern "C".
Yes - C++ can use C libraries.
Yeah. It's bad. Really bad. unsigned long
- just no. Return a properly typed BankAccount*
- the other languages will see it on the other end as a generic pointer (such as System.IntPtr) and there's no need to return an untyped pointer when the binary interface doesn't type pointers anyway.
extern "C" BankAccount* CreateBankAccount() {
return new BankAccount;
}
extern "C" void deposit(BankAccount* account, double amount) {
account->deposit(amount);
}
That basically looks fine with one proviso. Trying to use an integer type to hold a pointer is not a great idea—much better to use void*
since that, by definition, is the width of a pointer.
Actually, I think @DeadMG's answer is a cleaner approach than this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With