如何在C中使用C++的类

Today I had a little chat with Michiel on #gnome-nl regarding the use of C++ classes in C code (he started learning C again ;-)).

I was fascinated (well, sort of) by this, and tried to get something working. Here's the result:

* First we need a C++ class, using one header file (Test.hh)

class Test {
public:
void testfunc();
Test(int i);

private:
int testint;
};

and one implementation file (Test.cc)

#include <iostream>
#include "Test.hh"

using namespace std;

Test::Test(int i) {
this->testint = i;
}

void Test::testfunc() {
cout << "test " << this->testint << endl;
}

This is just basic C++ code.
* Then we need some glue code. This code is something in-between C and C++. Again, we got one header file (TestWrapper.h, just .h as it doesn't contain any C++ code)

typedef void CTest;

#ifdef __cplusplus
extern "C" {
#endif
CTest * test_new(int i);
void test_testfunc(const CTest *t);
void test_delete(CTest *t);
#ifdef __cplusplus
}
#endif

and the function implementations (TestWrapper.cc, .cc as it contains C++ code):

#include "TestWrapper.h"
#include "Test.hh"

extern "C" {

CTest * test_new(int i) {
Test *t = new Test(i);

return (CTest *)t;
}

void test_testfunc(const CTest *test) {
Test *t = (Test *)test;
t->testfunc();
}

void test_delete(CTest *test) {
Test *t = (Test *)test;

delete t;
}
}

Some things you should notice:
1. typedef void CTest
We typedef CTest to void. This way we can use "CTest *" in our C code as if it's a normal C type, whilst we have compile-time type checks (sort of at least :-)), and it's cleaner than always using "void *"
2. The use of "extern "C" { }" around all functions (both definitions and implementations). We need this so the compiler won't name-mangle the resulting binaries. If you want to see what name-mangling is:

$ cat test.c
#include <iostream>
using namespace std;

void test() {
cout << "test" << endl;
}

int main(int argc, char *argv[]) {
test();
return 0;
}
$ g++ -o nmtest test.c
$ ./nmtest
test
$ nm nmtest
*blablabla*
08048818 t _Z41__static_initialization_and_destruction_0ii
080487c4 T _Z4testv
U _ZNKSs4sizeEv@@GLIBCXX_3.4
U _ZNKSsixEj@@GLIBCXX_3.4
*blablabla*

As you can see, our "test()" function has been renamed to "_Z4testv" by the compiler. This is needed to allow polyphormism in C++, but we don't want this in our C wrapper of course, as we want to know the name of the function we will call!
This implies we need another function name for every polyphormistic (SP?) class function of our C++ class in the C wrapper. 
* At last, we need some code to test our work (main.c):

#include <stdio.h>
#include "TestWrapper.h"

int main() {
CTest *t = NULL;

t = test_new(5);
test_testfunc(t);
test_delete(t);
t = NULL;

return 0;
}

This is, once more, braindead simple (C) code, where we use the functions defined in TestWrapper.h.
* Last but not least, we need to compile everything. I made a basic Makefile to do this (Makefile):

CFLAGS=-Wall -Werror -g -ansi -pedantic -std=c89
CCFLAGS=-Wall -Werror -g
LDFLAGS=-g -Wall -lstd c++

OBJS=Test.o TestWrapper.o main.o
PROG=test

all: $(PROG)
default: all

%.o: %.cc
$(CC) $(CCFLAGS) -c $<

%.o: %.c
$(CC) $(CFLAGS) -c $<

$(PROG): $(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $@

clean:
rm -f $(OBJS)
rm -f $(PROG)

Now we can simply call "make" to build the project:

$ make
cc -Wall -Werror -g -c Test.cc
cc -Wall -Werror -g -c TestWrapper.cc
cc -Wall -Werror -g -ansi -pedantic -std=c89 -c main.c
cc Test.o TestWrapper.o main.o -g -Wall -lstd c++  -o test

Finally, we test the resulting binary:

$ ./test
test 5

which is the expected result.

Obviously, writing a wrapper like this by hand can be a boring task. It might be possible to automate/s cript this, but I don't know whether the result is worth the time one puts into it. Just use plain C, we don't need C++ 

from: http://blog.eikke.com/index.php/ikke/2005/11/03/using_c_classes_in_c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值