Archive for the ‘Development’ Category

How to call legacy funtions (from dlls) in a Java program

Friday, September 21st, 2007

Goal: Learn how to write a java wrapper around a native windows library.

Tooles I used:

  • eclipse (java alone would be enough)
  • Windows SDK (for the cl.exe and windows headers)

Result: Eclipse Project with all source and binary files

First let me introduce a very simple legacy library called Native.dll, the only function in it is “foo” which prints a hello message.

Let’s have a look at the header file:

#ifdef NATIVE_EXPORTS
#define NATIVE_API extern "C" __declspec(dllexport)
#else
#define NATIVE_API extern "C" __declspec(dllimport)
#endif

NATIVE_API void foo();

You can see the funtion foo has no parameter and gets exported as a “C” function.
For the export I define a macro NATIVE_API, it can be defined to an export or an import modifier depending on a macro called NATIVE_EXPORTS. If the macro NATIVE_EXPORTS is defined the NATIVE_API represents an export, otherwise an import. The import branch exists only for the case of a direct import in cpp, I use it to demonstrate it with a simple driver (demonstrated in a later section).

The implementation is just as simple as the header file:

#define NATIVE_EXPORTS
#include "Native.h"
#include

NATIVE_API void foo() {
printf(”hello from: foo\n”);
}

From top to bottom, I define the macro NATIVE_EXPORTS, thus the macro NATIVE_API defined in the header expands to an export. The second line includes the Native.h header, be aware that the first two lines must be in that order because otherwise NATIVE_API expands to an import.

Now we know the legacy library we want to call. To clear up things a little I wrote a driver to verify that the library is working as expected. The driver is coded as follows:


#include "Native.h"

void main() {
foo();
}

In the driver case I include Native.h without defining NATIVE_EXPORTS beforehand, thus the foo function gets imported.
To get the whole thing running we must compile it, the compile string for the library is cl Native.cpp -LD -FeNative.dll, the compile string for the driver is cl Driver.cpp /link Native.lib.

When we now execute Driver.exe the expected output hello from: foo will be generated.

Now as we have declared the legacy library we switch to the java side of the mess.

To get the pig flying we must declare a Java peer class, I called it nativelib.Native and declared it as follows:

package nativelib;
public class Native {
static {
System.loadLibrary("nativelib_Native");
}
public native static void NativeFoo();
}

In this class we must declare a method as native, usually and also in this case the method will be static. For our simple example our method has no parameters. The other part of the class is a static initializer where the native peer library gets loaded.

What! We compiled our library to the name Native.dll, but now you try to load a library called nativelib_Native.dll, why?
The answer to this question is philosophical, the philosophy of Sun when they invented Java was to rewrite everything you want in Java, not to include legacy stuff into your project. The reason for native calls is only a practical, you need them to connect to drivers and some OS stuff like GUI, Network. Therefor the default support from Java is not swell, we need to write special glue code to talk to your legacy library. But I’m sure there are OpenSource tools to do that for you, yet here we will do it manually.

To get your glue code running we need a header with the function definition first, to get it, we call javah -jni nativelib.Native, it generated a header with the nice definition for the NativeFoo method, heave a look:


/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class nativelib_Native */

#ifndef _Included_nativelib_Native
#define _Included_nativelib_Native
#ifdef __cplusplus
extern “C” {
#endif
/*
* Class: nativelib_Native
* Method: NativeFoo
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_nativelib_Native_NativeFoo
(JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

You can see the NativeFoo method from the package nativelib is now called Java_nativelib_Native_NativeFoo, and has two parameters, the first one is the environment and the second one is the java class, if we would have defined the method non static an object would be in place where now the class is.

I think the first part was easy, it’s never a problem to call a java program to generate a header file, but now we must implement the code behind. This might also be easy if you are experienced with windows library stuff, but it sure is not if you are a Java or .Net only coder. But do not fear the code is not too bulky:


#include
#include
#include
#include
#include
#include

#ifndef _Included_nativelib_Native
#define _Included_nativelib_Native
#ifdef __cplusplus
extern “C” {
#endif

#define LIB_NAME _T(”Native”)
#define LIB_EXT _T(”dll”)

TCHAR nativeFileName[MAX_PATH];

/*
* Class: nativelib_Native
* Method: NativeFoo
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_nativelib_Native_NativeFoo
(JNIEnv *, jclass)
{
HINSTANCE nativeLib;
FARPROC fooFunc;

nativeLib = ::LoadLibrary(nativeFileName);
if (nativeLib == NULL) {
printf(”Could not find library: Native.dll (%d)\n”, GetLastError());
return;
}

fooFunc = (FARPROC) ::GetProcAddress(nativeLib, _T(”foo”));
if (fooFunc == NULL) {
printf(”Could not find function foo() in Native.dll\n”);
} else {
fooFunc();
}

FreeLibrary(nativeLib);
}

#ifdef __cplusplus
}
#endif
#endif

BOOLEAN WINAPI DllMain
(IN HINSTANCE hDllHandle, IN DWORD nReason, IN LPVOID Reserved)
{
TCHAR fileName[MAX_PATH];
TCHAR driveName[_MAX_DRIVE];
TCHAR dirName[_MAX_DIR];
switch (nReason)
{
case DLL_PROCESS_ATTACH:
::GetModuleFileName(hDllHandle, fileName, MAX_PATH);
_tsplitpath_s(fileName, driveName, _MAX_DRIVE, dirName, _MAX_DIR, NULL, 0, NULL, 0);
_tmakepath_s(nativeFileName, driveName, dirName, LIB_NAME, LIB_EXT);
break;

case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

Ok, it is some code …

The first part (Java_nativelib_Native_NativeFoo) implements our method, the second part (DllMain) is just a helper. The DllMain is used to find the directory of this library at runtime as I want to search for the legacy library in exactly the directory.
Do I need this? No, you don’t but otherwise the legacy runtime must be in the library search path, which is the PATH in Windows and I do not want my stupid legacy library in that PATH. If you have a real problem you probably do not have this problem.

The function Java_nativelib_Native_NativeFoo uses the full path to the native legacy library (determined by DllMain) to load it with the LoadLibrary function. In case your legacy library is in the search PATH you could just enter the name (here Native) of the library instead of the absolute path to it.
If the library can be found we search for the function foo in the library, on success we simply execute it. When we are done with that we free the library with FreeLibrary to leave a clean environment.

So, our little experiment is almost done, we just need a driver in Java to test it out:

import nativelib.Native;

public class Main {
public static void main(String[] args) {
System.out.println(”pre Foo”);
Native.NativeFoo();
System.out.println(”post Foo”);
}
}

I expect you can handle the Java code above.
Add the libraries to the java.library.path (via -Djava.library.path=C:/path/to/the/glue/library). Remember we decided not to put your test libraries in the normal PATH.

Run it and the following output should emerge:


pre Foo
hello from: foo
post Foo

Now you made your first Java to native and Java to native legacy call!

To give you a little help, an me to remember that stuff in half a year or so I upload the eclipse project with all the files.

Best regards,
Markus

How to deliver a picture with ASP.Net

Monday, September 25th, 2006

Questions: “Is to possible to deliver a picture via ASP.Net?” and “Do I really have to write a dummy ASPX page?”

Short Answers: Yes. No!



More Sophisticated answer:

Usually one would write a so called ashx page, where the h means handler. If you have general requests to a page you should use such handler pages.



But the truth is your customer will see, as an image source for example: www.blabla.tld/funnypicture.ashx. And in fact I would not like this, because it’s simply not transperent. To come around this problem you have the possibility to implement the interface IHttpHandler in a “normal” class and publish the handler in the web.config of your application. The entry will look something like:

<httpHandlers>
<add verb=”GET” path=”SswLogo.gif” type=”GetImage” />
</httpHandlers>

“verb” describes the kind of http request handled, you may write a comma seperated list here (e.g.: verb=”GET,POST”), “path” means the url entered by the user (from your application root) and finally “type” describes the type name of the handler, with namespace if needed (e.g.: type=”MyNamespace.MyType”).

Download Sourcecode, Config and Screenshot

How to create a RGB (or any) image from any image kind in Java

Friday, March 10th, 2006
  1. Assume we have an image img
  2. Create a new buffered image:
    BufferedImage buffImg = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);
  3. copy the original image into the newly created buffered image:

    Graphics2D g = buffImg.createGraphics();
    g.drawImage(img, 0, 0, null);
    g.dispose();
  4. Be happy with your new buffered image.