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."

18 of 286 comments (clear)

  1. Cross language - what .Net gets right by cstec · · Score: 4, Insightful

    I don't even like .Net, but they won this round years ago.

    1. Re:Cross language - what .Net gets right by gigaherz · · Score: 4, Informative

      Not true. .NET assemblies are able to use both standard exports (C functions), and COM libraries (which can be coded in C, C++, VisualBasic 6, ...), and can also export COM interfaces to the .NET classes and through the use of assembly modification tools, also export C functions.

    2. Re:Cross language - what .Net gets right by rnturn · · Score: 3, Informative

      ``VMS was implemented in a variety of languages''

      (Hmm... I thought the lion's share (if not all) of VMS was written in BLISS.)

      You could definitely call, say, a VAX BASIC routine from a VAX FORTRAN program, VAX FORTRAN subroutines from VAX C programs, etc. And you didn't have to jump through a bunch of hoops to do it, either.

      --
      CUR ALLOC 20195.....5804M
    3. Re:Cross language - what .Net gets right by Dahamma · · Score: 4, Insightful

      .NET is already an extremely verbose platform that is many years ahead of its competition

      Wha? Its "competition" for what, exactly? Windows apps? So, wait, you are telling me a Microsoft development platform is ahead of its competition for developing Windows apps? And how is that interesting?

    4. Re:Cross language - what .Net gets right by cardpuncher · · Score: 4, Informative

      VMS was mostly written in BLISS, although there were chunks of Macro-32, particularly in the drivers. The big challenge in the Alpha port was effectively cross-compiling the Macro-32 code for Alpha hardware. Towards the end of Digital as an independent company, more development work was done in C.

      An early decision in the design of VAX/VMS was the definition of the "VAX Procedure Calling Standard" that dictated the instructions and mechanisms to be used for calling procedures, passing parameters and returning values, independent of language. All the compilers were expected to use this mechanism so that you could, for example, call a procedure written in VAX COBOL from VAX FORTRAN. This worked to a large extent, but it wasn't explicitly defined (and couldn't really be defined) whether compilers should use call-by-value, call-by-reference or call-by-descriptor for particular data types so additional semantic cruft was required to sort out the deails of parameter-passing. VAX C would sometimes pass a double-word argument in violation of the standard. The standard also had nothing to say about meta issues like run time initialisation, memory and thread usage, etc.

      That said, it was a revelation coming from an IBM world in which you'd sometimes have to write Assembler shims to patch up the calling conventions if you needed to get one language talking to another.

    5. Re:Cross language - what .Net gets right by TheRaven64 · · Score: 4, Insightful

      I talk a bit about .NET in TFA. It does some things right, but it still struggles with things like mutability. If you use F#, you get a language that is a lot like OCaml, and if you use it like OCaml, then it's fine. When you start trying to integrate with C#, then you find that they have different concepts of mutability. And you have to do it because the F# collection classes are much slower than their C# counterparts because the CLR lacks most of the optimisations that a typical OCaml implementation has to elide copies of immutable structures when your operation is implicitly destructive.

      --
      I am TheRaven on Soylent News
    6. Re:Cross language - what .Net gets right by TheRaven64 · · Score: 4, Informative

      VMS managed to get the idea of the platform ABI specifying procedure call conventions right very early on. It had quite an easy job though. C, BASIC and Fortran are all structured programming languages with basically the same set of primitive types. None of them have (or, in the VMS days, had) classes, late binding, or real garbage collection. BASIC is kind-of GC'd, but it doesn't have pointers and so everything passed across the language barrier from BASIC was by value, so the GC didn't have to do anything clever.

      It's worth remembering that when VMS was introduced, other platforms were still having problems getting C and Pascal to play nicely together (Pascal pushing arguments onto the stack in the opposite order to C), so that's not to belittle the achievement of VMS, but it's a very different world now that we have Simula and Smalltalk families of object orientation, various branches of functional languages, languages like Go and Erlang with (very different) first-class parallelism, and so on.

      --
      I am TheRaven on Soylent News
    7. Re:Cross language - what .Net gets right by Guy+Harris · · Score: 3, Insightful

      Passing in registers is not a standard C parameter passing method

      There's no such thing as "a standard C parameter passing method". Passing in registers is a perfectly legitimate C parameter passing method, used on several RISC architectures, such as SPARC, MIPS, 32-bit ARM, 64-bit ARM, and 64-bit {PowerPC/Power Architecture} (and probably most other RISC architectures), as well as x86-64 and z/Architecture.

      If there are more parameters than fit in the registers available for parameter passing, or if the parameters are in the variable-length portion of the argument list, they might be passed on the stack, and if the called function has no prototype in scope, the compiler might be forced to pass everything on the stack, but, in all other cases, if the ABI supports it, parameters can and will be passed on the stack.

    8. Re:Cross language - what .Net gets right by gbjbaanb · · Score: 3, Insightful

      don't - although the COM interop tooling for VB.NET is quite good, its all a massive performance penalty, and isn't quite as nice as its presented. The cross environment marshalling that's required (plus some pinning of data so the garbage collector becomes less efficient) means its there for convenience only. You wouldn't want to use it for heavy applications.

      Microsoft wants you to rewrite in .net (well, then they did, now they want you to rewrite it all in WinRT).

    9. Re:Cross language - what .Net gets right by raddan · · Score: 3, Informative

      P/Invoke, the other interop mechanism alluded to by the poster, is substantially faster than COM interop. I spent a summer at Microsoft Research investigating ways to make interop for .NET faster. There's maybe 20 or so cycles of overhead for P/Invoke, which is practically free from a performance standpoint. In addition to having its own [reference-counting] garbage collector, COM has extensive automatic-marshaling capabilities. These things make interop easy, but they add substantial overhead compared to P/Invoke. On the other hand, P/Invoke is somewhat painful to use, particularly if you want to avoid marshaling overheads and play nice with .NET's [tracing] garbage collector and managed type system. P/Invoke will often happily accept your ginned-up type signatures and then fail at runtime. Ouch.

      Coming from the Java world, I was totally blown away by what .NET can do. I can't speak for Microsoft myself, but I would be very surprised if .NET was not going to stick around for a long time. With the exception of perhaps Haskell, the .NET runtime is probably the most advanced managed runtime available to ordinary programmers (i.e., non-researchers). And, with some small exceptions (BigInteger performance... GRRR!), Mono is a close second. What the Scala compiler is capable of squeezing out of the poor, little JVM is astonishing, but Scala's performance is often bad in surprising ways, largely due to workarounds for shortcomings in the JVM's type system.

  2. Java, all you need. by magic+maverick+ · · Score: 5, Funny

    What do you need multiple languages for anyway? Java does everything you could want. Java is a powerful, object-orientated, cross-platform language, with fully developed GUIs, such as Swing.

    To demonstrate the superiority of Java, I can point to such leaders in their field as Eclipse, Minecraft, and this awesome applet I saw on someone's homepage once.

    Anyone still using ancient and difficult to use languages such as C++ (let alone C!) are obviously crazy, and probably should be committed for their own good before they go on spree of shooting (not just themselves, but) other people in the foot. Java makes it almost impossible to shoot yourself, let alone others, in the foot.

    Moreover, because Java is licensed under the GNU GPL, you can leverage the wisdom of crowds, and the powerful "many eyes make bugs shallow" concept to be confident that Java is the best.

    And with just-in-time, Java is as fast as any other language, so you don't have to worry about the speed of execution. Instead, you can focus on developer time, and Java's just faster in that regard.

    With built-in, from the ground up, support for Unicode, Java is there for the future, and is ready to be used across the multiverse (as soon as those aliens get their scripts into Unicode). Beat that C, with your lack of a string type.

    And if you aren't convinced, tell me why do so many top enterprises use this language? You don't see ads from Fortune 500 companies looking for Ruby "developers" do you?

    --
    HELP MY ACCOUNT HAS BEEN HACKED BY AN ILLIBERAL ART STUDENT SET TO DESTROY THE INTERWEBZ!
    1. Re:Java, all you need. by Dahamma · · Score: 4, Insightful

      Clearly there is some sarcasm/irony, as "What do you need multiple languages for anyway?", "and this awesome applet I saw on someone's homepage once" is pretty clear (unless he's a moron).

      But honestly the 80% of the rest of his points are actually true about Java - so either he doesn't really understand irony, he doesn't really understand Java, or he is just trying (rather successfully, IMO) to troll slashdot. I'm hoping that last case, in which I salute his efforts :)

  3. Java, C++ by stenvar · · Score: 4, Informative

    The fault here lies specifically with Java and C++. Java's JNI is poorly designed and makes no serious attempt to make interoperability easy because it is against Java's philosophy. C++'s runtime is deliberately completely implementation dependent because C++'s designers thought that might let implementors squeeze out a little bit of performance.

    Nevertheless, tools like Swig make even Java/C++ interoperation fairly easy, and many other languages try to accommodate C++ well (cf. Boost::Python).

    1. Re:Java, C++ by serviscope_minor · · Score: 3, Insightful

      Java's JNI is poorly designed and makes no serious attempt to make interoperability easy because it is against Java's philosophy

      I'm not an expert but I've done a bit of native language binding now and again. I didn't find JNI a massive barrel of laughs, but I didn't find it notably worse than other native bindings (e.g. CPython, ...). I was able to make calls in and out and throw java exceptions etc etc easily enough.

      Can you be more specific without reference to higher level wrapper tools (e.g. Boost:Python) since those aren't really part of the languages.

      C++'s runtime is deliberately completely implementation dependent because C++'s designers thought that might let implementors squeeze out a little bit of performance.

      They made the right choice here. C++ compiles have come on an awfully long way since the beginning. One of the biggest parts of the runtime (exceptions) have gone from slow and painful to essentially zero cost if you never use them. That ould never have happened if the rnutime was heavily specified.

      Besides, C++ is too portable for uch specification not to be quite harmful.

      --
      SJW n. One who posts facts.
  4. Re:this kind of comment system is dead by stenvar · · Score: 4, Informative

    I don't even know why anyone would even bother with c++. If it's a good fit, just use c.

    Because C++ lets people automate resource management and error handling, things that in C are manual and error prone. C++ also provides standards for abstraction, encapsulation, and substitutability, something that in C is not standardized and handled differently by every library. Despite C++'s many flaws and unnecessary complexity, it still is a better language than C for many projects.

  5. Sockets by jhol13 · · Score: 4, Insightful

    Use sockets. In majority of cases the performance is more than good enough, especially if designed properly, and you get network transparency "for free".
    Sure there are cases where sockets are not appropriate, but IMHO they are far too seldom used.

    1. Re:Sockets by Viol8 · · Score: 3, Informative

      We're talking about loading libraries , not inter process communication.

      But sure, instead of loading libs written in one language into another language you could just have N processes all written in different languages and communicate that way, but it would be at least an order of magnitude (probably 2) slower than directly linking in a library to your running process.

  6. 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.