11/03/05

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.

Obviously, writing a wrapper like this by hand can be a boring task. It might be possible to automate/script 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++ ;-)

Permalink . Ikke . 10:40:42 pm . 678 Words . Technology, Coding Corner . . 7780 views . 2 comments
Scratchbox working

Thanks to Bram (and VTK Computer) I got an old 20Gb hard drive, which I needed to be able to install a Scratchbox environment and play around with the Maemo platform.
I managed to install everything by now (although I had one crash again :-(), so I hope I'll be able to start hacking on some apps/libs soon. One of the things I'd love to get working is Avahi, the GPL'ed mDNS stack.

The obligatory shot:

I just followed these steps. They contain one error though: when editing your ~/.bash_profile, you got to add a line containing

export LC_ALL=en_GB

too.

Permalink . Ikke . 10:15:20 pm . 152 Words . Technology, Linux, Desktop, Coding Corner . . 736 views . 3 comments

10/27/05

770 and UGent VPN

So, I just got my Nokia 770 connected to the UGent VPN nerwork, which means I can connect to the internet when I'm near one of the access points. It wasn't too easy, and editting long texts on the device is fairly boring, so I'll stop here. More news when I'm near a "real" computer ;-)

Cheers!

Permalink . Ikke . 08:54:09 am . 55 Words . Technology, Linux, Networks . . 1055 views . 1 comment

10/18/05

Gnome for young children && 770 update

This theme mockup by Andreas Nilsson is actually pretty cool stuff IMHO, when used in an environment where young children/kids use the computer (eg in schools). I think it's pretty attractive, as long as the texts are easily readable.

Next to this, thanks to Philip and (obviously) Nokia itself, I was able to order my personal Nokia 770 from their Developer Program today. It should arrive in 1-3 days, so I'll be pretty stressed when checking the mail next days :-) When I saw (and even touched ;-)) the 770 at LinuxTag I was really impressed, let's hope it'll work well (/me crosses fingers for vpnc support) and bring a lot of pleasure on a development side :-)

Permalink . Ikke . 10:18:32 pm . 150 Words . Technology, Linux, Desktop . . 383 views . 2 comments

10/16/05

Screencasts part III: Victory!

Just found this wiki page which uses some other transcode options. I tried it, converted 2 seconds of a vnc recording to Xvid, and it works, jay :-)

Basicly:

$ emerge tightvnc vncrec transcode
$ vncserver
(enter password if necessary, edit the VNC xinitrc file,...)
$ vncrec -record test.vnc localhost:1
$ transcode -x vnc --use_rgb -i test.vnc -o test.avi -y xvid -k -f 10
$ mplayer test.avi

I'll try connecting to Vino now. Encoding takes a very long time, but well...

/me happy ;-)

Permalink . Ikke . 08:43:00 pm . 90 Words . Technology, Desktop . . 701 views . 2 comments

<< Previous Page :: Next Page >>