Slashdot Mirror


The Challenge of Cross-Language Interoperability

CowboyRobot writes "David Chisnall of the University of Cambridge describes how interfacing between languages is increasingly important. You can no longer expect a nontrivial application to be written in a single language. High-level languages typically call code written in lower-level languages as part of their standard libraries (for example, GUI rendering), but adding calls can be difficult. In particular, interfaces between two languages that are not C are often difficult to construct. Even relatively simple examples, such as bridging between C++ and Java, are not typically handled automatically and require a C interface. The problem of interfacing between languages is going to become increasingly important to compiler writers over the coming years."

1 of 286 comments (clear)

  1. Re:this kind of comment system is dead by ustolemyname · · Score: 3, Interesting

    As someone who's done a fair bit of the reverse, and has recently needed to write C bindings for a few other languages (go, ruby), I thought this shouldn't be nearly so hard as you describe. Here's what I've come up with:

    Example.cpp: Implements a class and C bindings for that class (The bindings could obviously be in a different file)
    #include "ExampleCBindings.h"
    #include
    class Example {
    public:
        Example(int v) { value = v; std::cout << "New Example(" << v << ")\n"; }
        ~Example() { std::cout << "Deleting Example(" << value << ")\n"; }
        int getValue() { return value; }
    private:
        int value;
    };

    extern "C" {
        Example_class* newExample(int value) { return (Example_class*) new Example(value); }
        void deleteExample(Example_class* example) { delete (Example*) example; }
        int ExampleGetValue(Example_class* example) { return ((Example*) example).getValue(); };
    }

    ExampleCBindings.h: Public C bindings
    #ifdef __cplusplus
    extern "C" {
    #endif
        typedef struct Example_t Example_class; // what I love most is that Example_t never exists ;)
        Example_class* newExample(int value);
        void deleteExample(Example_class* example);
        int ExampleGetValue(Example_class* example);
    #ifdef __cplusplus
    }
    #endif

    main.c: Simple C driver program that uses the api
    #include "ExampleCBindings.h"
    int main() {
        Example_class * ex1 = newExample(5);
        Example_class * ex2 = newExample(ExampleGetValue(ex1) + 2);
        deleteExample(ex1);
        deleteExample(ex2);
        return 0;
    }

    Limitations include:
    * Does not support objects existing on the stack. You're in C, this is the norm for opaque data structures.
    * Need to individually wrap every function. Would need to create separate wrappers for overloaded functions, or write a variadic function that doesn't enforce types (Sigh, neither language supports reflection)

    However, if you only wish to implement public functions, writing a script that autogenerates a wrapper like this would be fairly easy (I've done similar for a mocking framework for C code - now that's actually painful (not the script, inserting stubbed functions into a binary)). A little googling came up with a more formal attempt here.