Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Java

How to Wrap a C# Library for Use in Java

4.97/5 (22 votes)
5 May 2012CPOL3 min read 150.2K  
Wrap a C# library for use in Java, a folktale about an idiot coding at midnight.

Notice: Navigate the origin blog post for downloading source code that I've uploaded today.

You know, it's 3 am, today is my birthday, I have an AI tutorial class this afternoon and I've not slept yet. I'm so excited now. I've just archived the great idiots things that most idiots couldn't archive. I feel like the biggest idiot ever. From now on, I'm able to call an idiot C# method in the idiot language Java. I going to tell you how.

Before continuing, check if you've installed Windows OS, .NET framework and MS VS already.

Firstly, Prepare an Idiot C# Library by Yourself

Open your Notepad++ and type this code (do not copy here because this text is not colored):

C#
using System;
using System.Windows.Forms;

public class CSharpHelloWorld
{
    public CSharpHelloWorld() { }

    public void displayHelloWorld()
    {
        MessageBox.Show("Hello Java, I'm C#!", "Sample");
    }
}

I don't what this code can do, but I don't care. Save your code as CSharpHelloWorld.cs then make a .NET binary with what you've saved. Use this idiot command in Command Prompt:

csc /t:module CSharpHelloWorld.cs

If the command run OK, the result you get is file CSharpHelloWorld.netmodule, keep it safe, I suggest that you put this file in the refrigerator.

Secondly, Create a Java Byte Code that Uses Your C# Method

If your Notepad++ is still on, open a new tab and again, type the code:

C#
public class Test1 { 

    static {
        //System.loadLibrary("HelloWorld");
        System.load("D://HelloWorld.dll");
    }

    public native void displayHelloWorld();

    public static void main (String[] args) {
        Test1 t = new Test1();
        t.displayHelloWorld();
    }
}

After you finish typing, please read my explanation below, I'm trying to tell you the meaning of this nonsense code.

  • native modifier declares a body of a method that system provides. In this case, "system" includes the C# library that you'll make in the next ten minutes (or 4 hours, I'm not sure).
  • System.load(blah blah) tries to load a native-dll library onto memory.

So, you ask me: "Why don't you idiot guys build CSharpHelloWorld.cs into a DLL and finish this blog post?" No, life is not easy that way. A .NET library is not a native library. That why I'm telling you how to wrap it.

Build Test1.java, you have Test1.java. Don't try running this binary, it'll throw an exception while System loads the DLL library.

Now We Do the Most Exciting Work: Wrapper Library

In this part, you have to write a C++ library that calls displayHelloWorld() method from C# binary.

Using MS VS to create an empty C++ project, set output type is Library. Create 2 new folders 'Java' and 'MCPP' then copy file CSharpHelloWorld.netmodule into MCPP.

Create file 'HelloWork.h' in folder 'Java'. Please type slowly the code below (don't make a mistake, it's time consuming):

#include <jni.h>
/* Header for class Test1 */

#ifndef _Included_Test1
#define _Included_Test1
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Test1
 * Method:    displayHelloWorld
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_Test1_displayHelloWorld
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Then, create file 'HelloWorld.h' in folder 'MCPP'. Code here:

C++
#using <mscorlib.dll>
#using "CSharpHelloWorld.netmodule"

using namespace System;

public __gc class HelloWorldC
{
    public:
        // Provide .NET interop and garbage collecting to the pointer.
        CSharpHelloWorld __gc *t;
        HelloWorldC() {
            t = new CSharpHelloWorld();
            // Assign the reference a new instance of the object
        }
        
     // This inline function is called from the C++ Code
        void callCSharpHelloWorld() {
            t->displayHelloWorld();
        }
};

Sorry guys, don't miss the most important file: HelloWorld.cpp.

C++
#include <jni.h>
#include "Java\HelloWorld.h"

// The Managed C++ header containing the call to the C#
#include "MCPP\HelloWorld.h"

// This is the JNI call to the Managed C++ Class
// NOTE: When the java header was created, the package name was not include in the JNI call.
// This naming convention was corrected by adding the 
// "helloworld" name following the following syntax: 
// Java_<package name>_<class name>_<method name>
JNIEXPORT void JNICALL Java_Test1_displayHelloWorld  (JNIEnv *jn, jobject jobj) {

    // Instantiate the MC++ class.
    HelloWorldC* t = new HelloWorldC();

    // The actual call is made. 
    t->callCSharpHelloWorld();
}

Try compiling the project. ;) It doesn't work? Of course, who knows where jni.h is? By the way, you should know that jni.h helps the Java-C# interoption alot, read more materials. ;) Add the Include directories: Project -> Properties -> Configuration Properties -> VC++ Directories -> Include Directories -> Add 2 folders "%your jdk%/include" and "%your jdk%/include/win32".

It seems to be better :), there are some small errors while compiling the library, but I think Google will help you.

Build C++ project into HelloWorld.dll, then copy HelloWorld.dll and CSharpHelloWorld.netmodule to D:\. Run Test1.class and see what's happening.

A be-au-tiful dot-net face appears. Princess C# could date with the Beast Java. So be-au-tiful <3.

Image 1

Now I must take a nap. Everybody, birthday party at 7 am \:D/

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)