zoukankan      html  css  js  c++  java
  • Using C++ classes in 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 -lstdc++
    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 -lstdc++ -o test
    Finally, we test the resulting binary:
    $ ./test
    test 5
    which is the expected result.
  • 相关阅读:
    夺命雷公狗TP3.2.3商城7-----管理员的修改
    夺命雷公狗TP3.2.3商城6-----管理员的删除
    夺命雷公狗TP3.2.3商城5-----管理员的列表页和分页
    夺命雷公狗TP3.2.3商城4-----管理员的创建
    夺命雷公狗TP3.2.3商城3-----数据库的创建以及连接
    夺命雷公狗TP3.2.3商城2-----后台模版引入和后台控制器的创建
    夺命雷公狗TP3.2.3商城的搭建开篇1
    夺命雷公狗----网页版百度地图使用最新方法
    夺命雷公狗---linux NO:44 linux下php扩展的编译
    夺命雷公狗---linux NO:43 linux下编译apache整合php
  • 原文地址:https://www.cnblogs.com/hbt19860104/p/2627109.html
Copyright © 2011-2022 走看看