Thursday, May 3, 2012

How to wrap a C# library for using in Java, a folk tale about an idiot coding at midnight.



Hi guy, long time no see. I miss u so muchhhhh :x

Sorry readers, thing in front of me is the mirror. This post begins here.

U 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 almost idiots couldn't archive. I feel like the most idiot ever. From now on, I'm able to call an idiot C# method in the idiot language Java. I gonna tell you how.

Before continue, 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):
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 an .Net binary with what you've saved. Use this idiot command in Command Promt:
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 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:

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 minute (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 guy build CSharpHelloWorld.cs into a dll and finish this blog post?"
No, life is not easy that way. A dot net library is not a native library. That why I'm telling you how to wrap it.

Build Test1.java, you have Test1.class. Don't try running this binary, it'll throw an exception while System load 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 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:
#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
#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 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 happing.

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



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

P/s: Source code here (update May-05-2012)

See more : Use C# code in vbs

No comments:

Post a Comment