C # from IntPtr equivalent in Java

I have methods in C # that I call from .dll

[DllImport("somedll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int find([MarshalAs(UnmanagedType.AnsiBStr, SizeConst = 64)] string atr, out IntPtr int);

[DllImport("somedll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int getData(IntPtr int, int dataId, byte[] dataBuffer, ref int dataBufferSize);

      

In a C # call, this method looks like this:

static IntPtr number = IntPtr.Zero;
static int res = 0;
try{
    number = IntPtr.Zero;
    res = find(null, out number);   
    if (number == IntPtr.Zero)
                throw new ApplicationException("Something is wrong");
    uint dataBufferSize = 1024;
    res = getData(number, 1, null, ref dataBufferSize);
}

      

I haven't found what would be equivalent in Java.

If I do it like this:

public int find(String atr, Pointer int);

      

It says

java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokeInt(Native Method)
at com.sun.jna.Function.invoke(Function.java:419)
at com.sun.jna.Function.invoke(Function.java:354)
at com.sun.jna.Library$Handler.invoke(Library.java:244)

      

If I do it like this:

 public int find(String atr, IntByReference int);

      

Nothing happens.

Java code

IntByReference iref = new IntByReference();                     
res = find(null, iref);                                             
Pointer pointer = iref.getPointer();                            
int dataBufferSize = 1024;
byte[] dataBuffer = new byte[dataBufferSize];
res = getData(Pointer.nativeValue(pointer), 1, dataBuffer, dataBufferSize);

      

find returns 0, which means OK, but getData returns 6, which means that the memory address is not suitable. Nothing happens, I mean other res than 0.

+3


source to share


2 answers


IntByReference

- possible correct display (depending on what the pointer points to); however the value you are looking for is the eigenvalue "equal" within the matching one Pointer

. You can use instead PointerType

. In any case, it Invalid Memory Access

is associated with an attempt to access the internal memory that you have not allocated. Simple Pointer

does not allocate any memory. Initial side: usually you should use new Memory()

to initialize the pointer and allocate the memory it points to. (If you create one of the types ByReference

, it allocates the appropriate size, so this error goes away.)

An IntPtr

is an integer value representing the actual memory address that you should retrieve from IntByReference

or PointerType

using getPointer()

to get an object Pointer

and then pass it on Pointer.nativeValue()

to return the memory address ( long

) corresponding to yours IntPtr

.

Updated in response to edited code:

Several incorrect mappings that can cause problems:

The signature for getData()

requires to be dataBufferSize

a reference to an int, so you must use IntByReference

for this variable.

You cannot pass a simple array from Java to native. You must allocate memory for it. For example:



Pointer dataBuffer = new Memory(dataBufferSize);
// call getData();
byte[] foo = dataBuffer.getByteArray(0, dataBufferSize);

      

Additional update:

It looks like the method call find()

returns a pointer to the desired memory address, so you take the resulting IntByReference

from find()

and use it getValue()

to pass that integer to getData()

.

You may need to process the resulting array byte[]

. You haven't provided documentation for the API, but if it returns a different value for dataBufferSize

, you may need to truncate the byte array to make it fit. Since you called IntByReference

, you got down to getData()

how iref

, it would be:

byte[] dataByteArray = new byte[iref.getValue()];
System.arraycopy( dataBuffer, 0, dataByteArray, 0, iref.getValue());
String data = new String(dataByteArray, "UTF-8");

      

If the C string is encoded differently than ASCII, you may need to use a different conversion.

0


source


It works if I pass number.getValue () to getData (). Now res is 0.

Complete code:



IntByReference number=new IntByReference(0);                        
res = find(null, number);                                   
int dataBufferSize = 1024;
IntByReference iref=new IntByReference(dataBufferSize);
Pointer array = new Memory(dataBufferSize);                         
res = getData(number.getValue(),1, array,iref);                 
byte[] dataBuffer=array.getByteArray(0,dataBufferSize); 

      

0


source







All Articles