0

I have been given the task to convert a C# Windows Form GUI to a Java Swing GUI. I have to use the same library which is written in C. One of the functions in the library need the native handle of the window to be able to link the C program to the window. In the C# code the use of native handle is fairly simple and an Intptr is passed to the function. In java it is a different story. I have found a way to get the handle of the window using JNA (Java Native Access) and HWND a representation of the native handle. The problem is when I give the handle using HWND an Invalid memory access Exception pops up every time. Here is the code I am using.

Main Class:

    public class main {
    public static void main(String[] args) {
        JFrame jFrame = new JFrame();
        jFrame.setSize(5000,5000);
        jFrame.setVisible(true);
        final HWND ptrRef = new HWND(Native.getComponentPointer(jFrame));
        CLibrary cl = CLibrary.INSTANCE;
        System.out.println("Handle: "+ptrRef);
        String sPath = "C:\\Users\\markm\\IdeaProjects\\JFrameHandle\\Release";
        cl.clStart(ptrRef, sPath, true);

    }

}

CLibrary Interface:

    public interface CLibrary extends Library {
         Clibrary INSTANCE = (CLibrary) Native.loadLibrary("C:\\Users\\markm\\IdeaProjects\\JFrameHandle\\Release\\clibrary",CLibrary.class);
         void clStart(HWND parent, String libraryPath, boolean hidePanel);
}

Unfortunately I do not have access to the C code since I only have the .dll files but before I can get access to that code I need to know if am doing something wrong on my part. If someone could point me in the right direction on how to use window handles or maybe there os a way to pass a handle through JNI on the other end please do comment I could use all the help I can get.

Thanks in advance.

Mark Mizzi
  • 42
  • 7
  • 1
    What in the world is this C library doing that it's supposed to directly manipulate GUI windows owned by managed runtimes? – chrylis -cautiouslyoptimistic- Apr 15 '17 at 22:38
  • Since you're using a dll, you're effectively bound Windows OS. What's the point of the rewrite? – Amit Apr 15 '17 at 22:42
  • @chrylis - Well the c library is putting a 'window' on the main window. That is why I am trying to pass the handle of the main window to the library so that it has a point reference – Mark Mizzi Apr 15 '17 at 23:12
  • @Amit - I know it may be strange but there is a need to show that it can be done in java as well. I am student and it is an assignment so I can not argue on that issue sorry. – Mark Mizzi Apr 15 '17 at 23:13
  • 1
    *I have to use the same library which is written in C.* Says who? And *WHY*? This C library is written to work on a window created by C#? And someone thinks it will work just the same on a Java-created window? Will parts off a Ford pickup work in a Toyota Prius? It sounds like you've been given an impossible task. – Andrew Henle Apr 15 '17 at 23:35
  • @AndrewHenle - Well for now I have to try to make it work if the task is indeed proven to be impossible I can tell the owners to modify the C code but I have to do my part first and I think I am pretty close. – Mark Mizzi Apr 15 '17 at 23:56
  • Yeah i have this task to, do you figured out the sollution? – Adam Mudianto Jun 21 '20 at 11:15

1 Answers1

2

The Invalid Memory Access error indicates you haven't allocated native-side memory for whatever pointer you're passing to the function. Since the String and boolean aren't the problem, you know that passing the HWND isn't the correct mapping.

Without seeing the C API I can only guess but based on your description of it taking an IntPtr it's expecting the native address as an integer (either int or long depending on 32 bit or 64 bit).

I suspect you need to change your interface mapping to either long or int and pass Pointer.nativeValue(HWND.getPointer()) to it. (Or simplify your code to bypass the HWND storage, and simply get the integer initially using Pointer.nativeValue(Native.getComponentPointer(jFrame)).)

Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
  • Thanks for the input. I have just tried your solution which to me makes a lot sense since the C# code is giving a similar value it still is giving the same exception. I also have tried to give it an IntByReference which is what I found is the equivalent of IntPtr in Java and still the same result. I am beginning to suspect that the String argument is the problem. I was told that there might be a difference regarding encoding (UTF-8 vs UTF-16) but I am not sure what to do. – Mark Mizzi Apr 15 '17 at 23:51
  • Can you link to your documentation of the dll? – Daniel Widdis Apr 16 '17 at 00:12
  • Unfortunately I don not have any documentation. I will be getting more information about the dll soon. I will ask for the documentation as well. I know it is strange to not have the documentation but the assignment is about analyzing the code and being able to extract and create another version of the code with another language. Also the dll is of private property for now so I have to be very careful on what to show (that is why the library is called CLibrary. trying to be very generic). sorry if it is very difficult to help. – Mark Mizzi Apr 16 '17 at 00:19
  • how about just the C method signature for `clStart()` then? :) – Daniel Widdis Apr 16 '17 at 00:21
  • All I know about the method signature is this: clStart(? parent, char* libraryPath, boolean hidePanel) the parent I don't know what type it is. All I know is that it can take long and int for sure. – Mark Mizzi Apr 16 '17 at 00:26
  • 1
    I'd continue throwing various types of integers at `clStart`. Maybe `NativeLong`. You can pass a Pointer instead of the string, use `String.getBytes("UTF-16")` to get a byte array, initialize a new `Memory` object with that length plus one, and fill the buffer using `Memory.write()`. Don't forget to add a 0 byte to the end. – Daniel Widdis Apr 16 '17 at 00:30