7

I've spent many hours trying to use a C# function inside my Java Application but had no success... I wrote the following lib in C#:

public class Converter
{

    public Converter()
    {
    }

    public bool ConvertHtmlToPdf(String directoryPath)
    {
        //DO SOMETHING
    }
}

This dll calls another dll to make some operations but when I compile it I can find Dlls in my Realse folder and everything seems to be ok, so I compiled it using 32bit option, 64bit, and Any CPU option just to make sure that it's not my issue.

Analizing my dll files with Dependency Walker in 32 bit and Any CPU option it says that IESHIMS.DLL can't be found, and show this message:

Warning: At least one delay-load dependency module was not found. Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.

It doesn't occur with the 64bit file, nevertheless I can't find my ConvertHtmlToPdf function.

As I don't know if it is relevant or not, my second step was in the Java Code.

To load my library I do:

System.setProperty("jna.library.path", "C:\\Program Files (x86)\\Facilit\\Target App\\lib");

and:

public interface IConversorLibrary extends Library {

    IConversorLibrary INSTANCE = (IConversorLibrary) Native.loadLibrary("converter", IConversorLibrary.class);

    void ConvertHtmlToPdf(String directoryPath);
}

(The lib seems to be load successful, cause if I try to delete dll file with my application running it says that can't be deleted cause it's in using) and finally:

IConversorLibrary.INSTANCE.ConvertHtmlToPdf(directoryPath);

But the result is not really as I wish:

java.lang.UnsatisfiedLinkError: Error looking up function 'ConvertHtmlToPdf': Could not find the specified procedure.

I don't know what I'm doing wrong, I've tried many tutorials and many things, but anything seems to work, any help is really appreciated.

Victor Laerte
  • 6,446
  • 13
  • 53
  • 102
  • Setting `jna.library.path` is not really going to affect JNA; you would need to set `%PATH%` instead. The latter actually affects shared library loading, which `jna.library.path` does not. – technomage Aug 27 '13 at 23:30
  • If you don't see your function name listed in dependency walker, JNA certainly won't be able to find it. – technomage Aug 27 '13 at 23:30
  • 3
    JNA can load from DLLs that use C linkage. A C# class does not by default support any kind of C linkage. C++ supports C linkage with the `extern "C"` notation. – technomage Aug 27 '13 at 23:32
  • @technomage Is there a way make it "findable" to JNA? Some tutorial, or just an idea? – Victor Laerte Aug 27 '13 at 23:34
  • [This article](http://channel9.msdn.com/Forums/Coffeehouse/Do-you-know-a-tool-to-automate-making-C-DLLs-exports-callable-from-native-code) suggests you might be able to hack the C# DLL loading to do what you want. – technomage Aug 28 '13 at 11:20
  • Be sure to use the 64-bit depends with 64-bit DLLs; similarly for 32-bit. The docs do discuss that there are optional dependencies that will be marked missing and that you can ignore them. As @technomage says, until you make change to your build, you won't find any functions to Java to JNI/JNA to dynamically link to. – Tom Blodget Aug 28 '13 at 23:33

2 Answers2

4

This Nugget is super easy to use and works perfectly. https://www.nuget.org/packages/UnmanagedExports

You need Visual Studio 2012 (express). Once installed, just add [RGiesecke.DllExport.DllExport] before any static function you want to export. That's it!

Example:

C#

[RGiesecke.DllExport.DllExport]
public static int YourFunction(string data)
{
     /*Your code here*/
     return 1;
}

Java

Add the import at the top:

   import com.sun.jna.Native;

Add the interface in your class. Its your C# function name preceded by the letter "I":

  public interface IYourFunction extends com.sun.jna.Library
    {
       public int YourFunction(String tStr);
    };

Call your DLL where you need it in your class:

IYourFunction iYourFunction = (IYourFunction )Native.loadLibrary("full or relative path to DLL withouth the .dll extention", IYourFunction.class);//call JNA
        System.out.println("Returned: " + IYourFunction.YourFunction("some parameter"));
John
  • 1,011
  • 11
  • 18
  • 2
    Really? I'll try it :D – Victor Laerte Oct 11 '13 at 16:45
  • Tried this myself. Remarkably easy. Only catch is processor architecture, which must match between your project & unit test projects in VS, your default processor architecture setting in VS under Test | Test Settings | Default Processor Architecture, and the bitness of the interop environment that loads the .dll. – bwerks Apr 02 '19 at 14:54
3

As said by technomage:

JNA can load from DLLs that use C linkage. A C# class does not by default support any kind of C linkage. C++ supports C linkage with the extern "C" notation.

This article shows a way to make C# DLLs methods callable like C-style DLL, unfortunately it's a quite complex.

Victor Laerte
  • 6,446
  • 13
  • 53
  • 102