Solved

Combine Java with C

Posted on 1998-05-30
6
470 Views
Last Modified: 2013-11-23
How can i combine c code ( as methods in an implementation of rmi serverimpl ) with Java ??
Can it be doen ??? how ??? how do i pass parameters
from java to c functions ???

0
Comment
Question by:sector
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
6 Comments
 
LVL 32

Expert Comment

by:jhance
ID: 1221766
You didn't mention which platform or JDK version you are using so I'll note the most universal way of doing it.  You define a method as "native".  This tells Java that the underlying implementation of the function is not Java but implented in C (or some other language) on the hosting operating system.  Check the documentation for your Java development environment on how to implement and use a native method.
0
 

Expert Comment

by:sdaxm11
ID: 1221768
To use a C program you have to use a Java Native  Method. Basicly you have to defind the C program in Java, pass the varibles in vative types and recive the answers.

remember to generate the the C header not write it

p.s it is advisable to use C++ as it fits the OO programing
The only example i have is from Learn more java in 21 days so here goes

the pond example

pond.cpp-----------------------
#include "Pond.h"

// Global field IDs
jfieldID fLengthID;
jfieldID fWidthID;
jfieldID fDepthID;

void JNICALL Java_Pond_initPond(JNIEnv* env, jclass thisClass) {
  // Find the fields
  fLengthID = env->GetFieldID(thisClass, "length", "F");
  fWidthID = env->GetFieldID(thisClass, "width", "F");
  fDepthID = env->GetFieldID(thisClass, "depth", "F");
}

jfloat JNICALL Java_Pond_getVolume(JNIEnv* env, jobject thisObject) {
  // Get the field values
  jfloat length = env->GetFloatField(thisObject, fLengthID);
  jfloat width = env->GetFloatField(thisObject, fWidthID);
  jfloat depth = env->GetFloatField(thisObject, fDepthID);

  // Calculate and return the volume
  return length * width * depth * 7.5f;
}
_______________________________________

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

#ifndef _Included_Pond
#define _Included_Pond
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Pond
 * Method:    initPond
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_Pond_initPond
  (JNIEnv *, jclass);

/*
 * Class:     Pond
 * Method:    getVolume
 * Signature: ()F
 */
JNIEXPORT jfloat JNICALL Java_Pond_getVolume
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

-------------------------------------------------------------

pond.java---------------------------------------------
import java.io.*;

public class Pond implements Serializable {
  private float length, width, depth;

  // Constructors
  public Pond() {
    this (0.0f, 0.0f, 0.0f);
  }

  public Pond(float l, float w, float d) {
    length = l;
    width = w;
    depth = d;
  }

  // Accessor methods
  public float getLength() {
    return length;
  }
 
  public void setLength(float l) {
    length = l;
  }

  public float getWidth() {
    return width;
  }

  public void setWidth(float w) {
    width = w;
  }

  public float getDepth() {
    return depth;
  }

  public void setDepth(float d) {
    depth = d;
  }

  // Natives
  private static native void initPond();
  public native float getVolume();

  // Static startup code
  static {
    System.loadLibrary("Pond");
    initPond();
  }
}
-----------------------------------------------------------------

pondTest.java--------------------------------------------
public class PondTest {
  public static void main(String[] args) {
    // Make sure we have the right number of args
    if (args.length != 3) {
      System.out.println("Usage: java PondTest Length Width Depth");
      System.exit(0);
    }

    // Convert the args to floats
    float length = Float.valueOf(args[0]).floatValue();
    float width = Float.valueOf(args[1]).floatValue();
    float depth = Float.valueOf(args[2]).floatValue();

    // Create the Pond object and display the volume in gallons
    Pond pond = new Pond(length, width, depth);
    System.out.println("Pond length = " + pond.getLength() + " feet");
    System.out.println("Pond width  = " + pond.getWidth() + " feet");
    System.out.println("Pond depth  = " + pond.getDepth() + " feet");
    System.out.println("Pond volume = " + pond.getVolume() + " gallons");
  }
}
-----------------------------------------------------------


0
 

Expert Comment

by:sdaxm11
ID: 1221770
the c++ program must be a DLL
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 4

Accepted Solution

by:
evijay earned 300 total points
ID: 1221771
Let me illustrate the whole process with example

Suppose you have a java class RS232 in package bird. This class has a method printit which is implemented in C. These are the steps to integrate this C method in java program.

        Let me suppose that you are working in a directory say
        c:\work
        now create a directory in work by name bird
        c:\work> md bird
        change to directory bird
        c:work> cd bird

        create a file by name RS232.java with following contents

        package bird;
        public class RS232 {

        public static native void printIt();
        static {
        System.loadLibrary("rs232");
        }

        public static void main(String args[])
        {
        printIt();
        }
        }

        compile the file using

        c:\work\bird>javac RS232.java

        now set the class path to point to c:\work (the parent directory of bird) (this is most important)
        c:\work\bird> set classpath=c:\work;%classpath%    

        create stub file
        c:\work\bird> javah -jni bird.RS232

        This creates a file bird_RS232.h. Now,create a file rs232.c (native implementation) in bird directory with the following contents

        #include "bird_RS232.h"

        JNIEXPORT void JNICALL Java_bird_RS232_printIt
          (JNIEnv *env, jclass mclass)
        {
        printf("Hello World !!\n");

        }

        compile the file using VC++ compiler as follows

        C:\work\bird>cl -Ic:\jdk1.1.4\include -Ic:\jdk1.1.4\include\win32  -LD rs232.c -Fers232.dll c:\jdk1.1.4\lib\javai.lib

        (change the jdk directory to appropriate to your installation. I am assuming that my jdk is in jdk1.1.4)

        Now, run the program as
        c:\work\bird> java bird.RS232


This is just a simple example. Now to go to complex examples where in we pass parameters to C programs etc.,.
Here are some very good articles you can look at
The first link is an introduction. While the second link is an advanced topic.

http://www.javaworld.com/javaworld/jw-07-1997/jw-07-javadev.html 
http://www.javaworld.com/javaworld/javatips/jw-javatip54.html


0
 
LVL 4

Expert Comment

by:evijay
ID: 1221772


This example will explain step-by-step the creation of an application use C native code. This example uses Sun's JNI 1.1. It will also demonstrate C if faster than Java by doing 500 000 calls to strlen and to
java.lang.String.length().

     1.Create the Main.java file and compile it using javac Main.java

                    class Main
                    {
                        public static void main(String [] args)
                        {
                            CJava j=new CJava();
                            System.out.println(j.perfTest("Just a Test!"));
                        }
                    }

     2.Create the CJava.java file and compile it using javac CJava.java

                    class CJava

                        static {
                            System.loadLibrary("CJava");
                        }

                        public int compute(String s) {
                        return s.length();
                        }

                        public native String perfTest(String s);
                    }

          This class contains the definition for the perfTest method. It will be called by the main method to display a String. This class also loads the CJava.dll (Win32), or the CJava.so (Unix) dynamic library.
          Note that the mapping from a library name to a specific filename is done in a system-specific manner.
          The compute() method is used to return the string length to the native code. It would be faster to call directly the java.lang.String.length() method from native code, but the example would become less
          clear.

     3.Create the .h file using javah -jni CJava

          This tool generate a header file with a .h extension contains the header for the perfTest C native method. You don't need to modify this file.

     4.Create the CJava.cpp file and compile it.

                    #include <jni.h>
                    #include <stdio.h>
                    #include <string.h>
                    #include "CJava.h"

                    JNIEXPORT jstring JNICALL Java_CJava_perfTest(JNIEnv *env, jobject obj, jstring s)
                    {
                    char *buf=new char[100];
                    long a,i,j;
                    printf("Entering native method.\n\n");

                    const char *str=env->GetStringUTFChars(s,0);
                    printf("The input string is: %s\n",str);

                    jclass cls = env->GetObjectClass(obj);
                    jmethodID mid = env->GetMethodID(cls, "compute", "(Ljava/lang/String;)I");


                    printf("Using C function to get the string length:\n");
                    for (a=1;a<500000;a++) j=strlen(str);
                    printf("C size: %d\n",j);


                    printf("Calling java method from native code to get the string length:\n");
                    for (a=1;a<500000;a++) i=env->CallIntMethod(obj, mid,s);
                    printf("Java size: %d\n",i);


                    printf("Creating the string returned by the function.\n");
                    sprintf(buf,"\nString %s :\nJava length=%d\nC length=%d\n",str,i,j);


                    env->ReleaseStringUTFChars(s,0);
                    printf("Leaving native code.\n");
                    return env->NewStringUTF(buf);
                    }

          To compile it on a win32 machine using Visual C++ , simply enter the command:

                    cl -I"C:\program files\javasoft\jdk1.1.4\include" -I"C:\program files\javasoft\jdk1.1.4\include\win32" /LD CJava.cpp

     5.Launch the main class using java Main

          You should see a big performance difference between the first loop (using strlen() C function) and the other one (using java.lang.String.length()). A large overhead for calling java methods inside native
          code make this example unuseful.
           
0
 
LVL 4

Expert Comment

by:evijay
ID: 1221773
Another site for interesting info on native methods

              http://www.inside-java.com/articles/native/index.htm
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
servlet web applications   metadata-complete="true" or false 3 191
How do I remove an object from a 3 53
spring maven example issues 3 40
junit as external jar or library 7 38
An old method to applying the Singleton pattern in your Java code is to check if a static instance, defined in the same class that needs to be instantiated once and only once, is null and then create a new instance; otherwise, the pre-existing insta…
Introduction This article is the second of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers the basic installation and configuration of the test automation tools used by…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

756 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question