Click here to Skip to main content
15,860,972 members
Articles / Programming Languages / Java / Java SE

C# method calls within a Java program

Rate me:
Please Sign up or sign in to vote.
3.57/5 (25 votes)
16 Feb 2006CPOL4 min read 283.5K   7.7K   60   54
Using C# from Java through JNI just got a little easier to understand.

Sample Image - javacsharp.jpg

Introduction

Have you ever (for some reason or other) needed to use C# from within a Java program? Ever wondered how you could possibly make C# calls from within Java? Well, I will try to explain what is needed in this whole process.

Background

I was working on some Keyboard Hooking problems, and found it very easy to develop it using C#. The problem was that I was trying to develop a solution (originally) for a Java based program. After much Internet searching, I finally stumbled onto a really good article that started to put the pieces together. The article "Experience in integrating Java with C# and .NET" by Judith Bishop, R. Nigel Horspool, and Basil Worrall, was the insight I needed to start this project.

That article does show a method to use C# within a Java program; however, I didn't find it was easy to understand the whole process. After I actually had C# working within a Java program, I realized that the process could become a CodeProject article (my first article).

Using the Code

Image 2

This figure is taken from the article "Experience in integrating Java with C# and .NET" by Judith Bishop, R. Nigel Horspool, and Basil Worrall.

I guess the best way to use this code is to experiment with it, and use it as a template for a project. I obviously didn't do anything terribly complicated, by just putting up a "Hello World" example, but I wanted people to see the easiest way possible first. The sample code is simply a console based Java program which will show the "Hello World, from C#" message. I'm also including all the source code and projects in all four languages.

Why the need for so many wrappers, you may ask. Well, several layers of wrapping are needed because the DLL produced by compiling a C# program into a library is not compatible with Java's JNI. The double layer of C++ above is required because the DLL with which the JNI subsystem interacts with has to be static, procedural code (not object oriented). So, the first layer is essentially C code. Fortunately, static C code will accommodate (static) pointers to C++ objects. It's doubtful whether the static C code could interact directly with a C# object, since there are things like garbage collection to consider.

Java Section

I was using Netbeans 4.0 as my main Java IDE at the time, and because of that, the process of using native code was a little more complicated. The reason for that is because a Netbeans project wants to put code inside packages rather than just use the default namespace. The javah console program, however, doesn't look at the package, and therefore doesn't correctly make the header in the right namespace. So, as I found out, there's a simple two second fix, which just requires you to edit the generated header file to correctly make the connection through JNI to the native methods in C++.

Here is the only Java code, which resides in the helloworld package:

Java
public class HelloWorld {
    public native void displayHelloWorld();
    static {
        System.loadLibrary("HelloWorld");
    }
    
    public static void main (String[] args) {
        new HelloWorld().displayHelloWorld();
    }
}

So then, to make this into the header which is needed by the C++ library, this command needed to be run:

javah -jni helloworld.java

That step produces the following header:

C++
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorlds
#define _Included_HelloWorld
#ifdef _cplusplus
extern "C" {
#endif
/*
 * Class:        HelloWorld
 * Method:        displayHelloWorld
 * Signature:    ()V
 */
JNIEXPORT void JNICALL 
  Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

However, if we don't change the generated header, then the JNI call will fail as the method has a different signature due to NetBeans and the package. So the JNIEXPORT line is changed to:

Java
JNIEXPORT void JNICALL Java_helloworld_HelloWorld_displayHelloWorld (JNIEnv *, jobject);

C++ Library

The purpose of the C++ library is to become the JNI Wrapper for the call (through the Managed C++ wrapper) to the endpoint C# code.

C++
#include <jni.h>

// This is the java header created using the javah -jni command.
#include "Java\HelloWorld.h"

// This is the Managed C++ header that contains 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 included
//       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_helloworld_HelloWorld_displayHelloWorld(JNIEnv *jn, jobject jobj) {

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

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

Managed C++ Library

MC++
#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();
        }
};

C# Library

The step that is required for the interaction between Managed C++ and C# is that the CSharpHelloWorld library be compiled as a .netmodule. To do this, the following command must be run from either the console or as a post-build event within the C# project (I streamlined the process by using post-build):

csc /debug /t:module "$(OutDir)\$(ProjectName).dll"

There is barely any code in this project, as I only wanted to show the simplest example possible. And what, my friends, is more simple than 'HelloWorld'?

C#
using System;

public class CSharpHelloWorld
{
    public CSharpHelloWorld() {}

    /// <summary>
    /// displayHelloWorld will be the method called from within java.
    /// </summary>
    public void displayHelloWorld() 
    {
        Console.WriteLine("Hello World, from C#!");
    }
}

Points of Interest

Working with Java JNI is quite a pain, especially by using Netbeans as an IDE. Hopefully, I've given you some insight as to what to expect at the different steps of this process. I must have hit every single roadblock in this project, and taken the time to look up what was needed.

History

  • Version 1.0 - First release!

License

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


Written By
Web Developer
Canada Canada
I'm current a 3rd year Computer Engineering Technology : Software Developer student at St. Lawrence College in Kingston, Ontario.

I usually get myself into some of the more cool projects like neural nets or cross platform applications.

Comments and Discussions

 
QuestionHow do we create a .net module from the C# file ? Pin
Sandeep TDS21-Jul-16 0:02
Sandeep TDS21-Jul-16 0:02 
SuggestionImprovements to generate header file. Pin
Visruth CV21-Aug-15 3:40
Visruth CV21-Aug-15 3:40 
QuestionRegarding Net Module File Pin
Member 1155455721-Apr-15 2:14
Member 1155455721-Apr-15 2:14 
Questionwhat I can do if C# dll will call another .NET dll ? Pin
kingbird6-Jun-13 15:31
kingbird6-Jun-13 15:31 
AnswerJava Wifi Pin
Member 86527495-Dec-12 3:52
Member 86527495-Dec-12 3:52 
GeneralMy vote of 5 Pin
Member 962482423-Nov-12 3:40
Member 962482423-Nov-12 3:40 
SuggestionCS file for NetModule Pin
Member 962482423-Nov-12 3:39
Member 962482423-Nov-12 3:39 
GeneralMy vote of 3 Pin
gauravkhullar16908-May-12 1:02
gauravkhullar16908-May-12 1:02 
GeneralMainsoft's Grasshopper takes care of creating jar file out of .net project and is extremely easy to use! Pin
Deswick13-Jun-11 7:16
Deswick13-Jun-11 7:16 
GeneralMy vote of 5 Pin
Mouhoub Amine4-Jun-11 1:09
Mouhoub Amine4-Jun-11 1:09 
GeneralCan't generate header file Pin
Saw Thanda Oo28-Dec-10 21:48
Saw Thanda Oo28-Dec-10 21:48 
Generaljavah does deal with packages Pin
jschell6-Sep-10 8:51
jschell6-Sep-10 8:51 
GeneralNeed to call java from within C# Pin
DennisZweigle26-Feb-10 11:22
DennisZweigle26-Feb-10 11:22 
QuestionAny simple solution for Java program call C# DLL ? Pin
kaccy_oon14-Jan-10 14:22
kaccy_oon14-Jan-10 14:22 
Generaljni4net [modified] Pin
Zamboch4-Nov-09 10:25
Zamboch4-Nov-09 10:25 
GeneralC++ class compilation error Pin
shahnawaz.patel25-Oct-09 1:53
shahnawaz.patel25-Oct-09 1:53 
Questionwhere's the dll come from? Pin
maul_oke18-Aug-09 22:23
maul_oke18-Aug-09 22:23 
AnswerRe: where's the dll come from? Pin
macambabun13-May-13 21:27
macambabun13-May-13 21:27 
QuestionHow can I call java class with in C# Pin
Hari Om Prakash Sharma18-Mar-09 0:41
Hari Om Prakash Sharma18-Mar-09 0:41 
Generaldoes this source and description work for me its not kindly help Pin
G.Makesh18-Nov-07 23:09
G.Makesh18-Nov-07 23:09 
QuestionC# with reference to 3rd party DLLs Pin
Lee Rong13-May-07 7:56
Lee Rong13-May-07 7:56 
AnswerRe: C# with reference to 3rd party DLLs Pin
abdulcalicut11-Jun-07 23:48
abdulcalicut11-Jun-07 23:48 
AnswerRe: C# with reference to 3rd party DLLs Pin
abdulcalicut14-Jun-07 0:29
abdulcalicut14-Jun-07 0:29 
GeneralRe: C# with reference to 3rd party DLLs Pin
Jorge M. R. Santos16-Nov-07 10:25
Jorge M. R. Santos16-Nov-07 10:25 
GeneralRe: C# with reference to 3rd party DLLs Pin
LarsKongo6-Mar-08 4:06
LarsKongo6-Mar-08 4:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.