JNA non-const String member of struct - string

I have a C function that expects a struct that contains a non-const String.
typedef struct _A {
char* str;
} A;
void myFunc(A* aptr) { ... }
I've tried for a long time to pass this thing via JNA but didn't manage so far.
public class A extends Structure {
public String str;
protected List getFieldOrder() { ...
}
doesn't work because String will be turned into a const char* instead of char* which I need.
public class A extends Structure {
public byte[] str;
protected List getFieldOrder() { ...
}
doesn't work because the byte array inside a struct gets turned into contiguous memory and not a pointer.
I know I can do it by using Memory and copying the String over. But I can't imagine that this is the preferred way to do it.
I also tried something like
public class NonConstStringMember extends Structure {
public static class ByReference extends NonConstStringMember implements Structure.ByReference {}
public byte[] stringMember;
protected List getFieldOrder() { ...
}
public class A extends Structure {
public NonConstStringMember.ByReference str;
}
but it doesn't work either, maybe because of alignment issues.
What is the preferred way to do this with JNA?

Assuming you want this to point to an arbitrary buffer which you may write to, use Pointer (and assign it a Memory value if you're allocating the buffer).
You then use Pointer.getString(0) or Pointer.setString(0, s) to manipulate the buffer contents.
EDIT
Windows libraries usually have an ascii or unicode version of most functions. While in most cases you can define a single Structure for use in both cases, sometimes you need to provide a little additional handling to ensure the correct types are used. Since the two modes are rarely, if ever, used simultaneously, JNA sets up options to default to one or the other (automatically mapping to the right function suffix, and automatically mapping String to either native const char* or const wchar_t* depending on the mode).
Use setWideString() if using unicode mode and setString() otherwise, or make some accessors on your Structure to handle that for you automatically. For example:
class MyStructure extends Structure {
private static final boolean ASCII = Boolean.getBoolean("w32.ascii");
public Pointer stringBuffer = new Memory(X);
void setStringBuffer(String s) {
stringBuffer.setString(0, s, ASCII);
}
String getStringBuffer() {
return stringBuffer.getString(0, ASCII);
}
}
EDIT
Please note that in most cases you should use a String as the field type and rely on a TypeMapper to use WString behind the scenes where appropriate (e.g. User32 and W32APIOptions.DEFAULT_OPTIONS).

Related

Mapping a structure inside a union in JNA

I am attempting to map the kstat library in Solaris 11.3 to Java using JNA. While I've managed to get most of the structures working, I've spent the last 24 hours fighting with a particularly difficult union-within-a-structure-within-a-union.
I am successfully retrieving a pointer to a kstat_named structure I need using kstat_data_lookup(). My code properly retrieves most of the data (name, data_type, and non-struct members of the union) in this C structure:
typedef struct kstat_named {
char name[KSTAT_STRLEN]; /* name of counter */
uchar_t data_type; /* data type */
union {
charc[16]; /* enough for 128-bit ints */
struct {
union {
char *ptr; /* NULL-terminated string */
} addr;
uint32_t len; /* length of string */
} str;
int32_t i32;
uint32_t ui32;
int64_t i64;
uint64_t ui64;
/* These structure members are obsolete */
int32_t l;
uint32_t ul;
int64_t ll;
uint64_t ull;
} value; /* value of counter */
} kstat_named_t;
I have mapped this in JNA as follows:
class KstatNamed extends Structure {
public static class UNION extends Union {
public byte[] charc = new byte[16]; // enough for 128-bit ints
public Pointer str; // KstatNamedString
public int i32;
public int ui32;
public long i64;
public long ui64;
}
public byte[] name = new byte[KSTAT_STRLEN]; // name of counter
public byte data_type; // data type
public UNION value; // value of counter
public KstatNamed() {
super();
}
public KstatNamed(Pointer p) {
super();
this.useMemory(p);
this.read();
}
#Override
public void read() {
super.read();
switch (data_type) {
case KSTAT_DATA_CHAR:
value.setType(byte[].class);
break;
case KSTAT_DATA_STRING:
value.setType(Pointer.class);
break;
case KSTAT_DATA_INT32:
case KSTAT_DATA_UINT32:
value.setType(int.class);
break;
case KSTAT_DATA_INT64:
case KSTAT_DATA_UINT64:
value.setType(long.class);
break;
default:
break;
}
value.read();
}
#Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "name", "data_type", "value" });
}
}
This code works correctly for int32 types (KSTAT_DATA_INT32). However, when the data type is KSTAT_DATA_STRING, which corresponds to the str structure inside the union, I am not having any success in properly retrieving the data.
I have mapped the nested structure like this:
class KstatNamedString extends Structure {
public static class UNION extends Union {
public Pointer ptr; // NULL-terminated string
}
public UNION addr;
public int len; // length of string
public KstatNamedString() {
super();
}
public KstatNamedString(Pointer p) {
super();
this.useMemory(p);
this.read();
}
#Override
public void read() {
super.read();
addr.setType(Pointer.class);
addr.read();
}
#Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "addr", "len" });
}
}
Ultimately I'm trying to replicate the behavior of this C macro:
#define KSTAT_NAMED_STR_PTR(knptr) ((knptr)->value.str.addr.ptr)
I've tried multiple different methods of trying to get access to the above structure, but it never seems to read the correct data (the len value is in the millions and attempting to read the string ptr causes segfault). I've tried:
Pointer p = LibKstat.INSTANCE.kstat_data_lookup(ksp, name);
KstatNamed data = new KstatNamed(p);
KstatNamedString str = new KstatNamedString(data.value.str);
return str.addr.ptr.getString(0); // <--- Segfault on C side
I've also tried:
Specifying KstatNamedString as the type instead of the Pointer type
Using various combinations of ByReference in both the structures and the unions
I've googled everywhere, including trying what I thought was a promising result here, but nothing seems to work.
I'm sure I'm missing something simple.
Use KstatNamedString instead of Pointer type.
Change your pointer-based constructors like this:
public KstatNamed(Pointer p) {
super(p);
this.read();
}
public KstatNamedString(Pointer p) {
super(p);
this.read();
}
and change the addr field of the str struct field to be a simple Pointer (no need for the union bits around it).
public Pointer /*UNION*/ addr;
Run your JVM with -Djna.dump_memory=true and print your newly-initialized Structure as a string. That will show you how JNA interprets the memory layout of the struct, and how the native memory is initialized. That should help you determine how to extract the string you're looking for (assuming it's there).
You can also tune your union read() method to initially read only the type field (using Structure.readField("data_type")) before setting the union type.

In Haxe, how do you pass Enum values in functions, and then convert them to Strings within the function?

I can't seem to get this working, but I'd be surprised if it wasn't possible in Haxe.
I'm trying to pass a couple of Enum values defined in my game to a function, so that it can then concatenate them as String types and pass that to other functions.
Example:
// In a general Entity class:
public override function kill():Void {
messages.dispatchCombined(entityType, ListMessages.KILLED);
super.kill();
}
And in my Messages.hx class:
package common;
import msignal.Signal.Signal1;
/**
* A Message / Event class using Signals bound to String names.
* #author Pierre Chamberlain
*/
class Messages{
var _messages:MessagesDef;
public function new() {
_messages = new MessagesDef();
}
public function add(pType:String, pCallback:FuncDef) {
if (_messages[pType] == null) {
_messages[pType] = new Signal1<Dynamic>();
}
var signals = _messages[pType];
signals.add( pCallback );
}
public function dispatch(pType:String, pArg:Dynamic):Bool {
var signals = _messages[pType];
if (signals == null) return false;
signals.dispatch(pArg);
return true;
}
//Compiler doesn't like passing enums :(
public inline function addCombined(pSource:Enum, pEvent:Enum, pCallback:FuncDef) {
add( combine(pSource, pEvent), pCallback );
}
public inline function dispatchCombined(pSource:Enum, pEvent:Enum, pArg:Dynamic):Bool {
return dispatch( combine(pSource, pEvent), pArg);
}
//How can I just pass the enum "names" as strings?
static inline function combine(a:Enum, b:Enum):String {
return String(a) + ":" + String(b);
}
}
typedef MessagesDef = Map<String, Signal1<Dynamic>>;
typedef FuncDef = Dynamic->Void;
Note how addCombined, dispatchCombined and combine expect an "Enum" type, but in this case I'm not sure if Haxe actually expects the entire Enum "class" to be passed (ie: ListMessages instead of ListMessages.KILLED) or if a value should work. Anyways, compiler doesn't like it - so I'm assuming another special Type has to be used.
Is there another way to go about passing enums and resolving them to strings?
I think you need EnumValue as parameter type (if it is only for enum values), and use Std.String to convert to String values.
static inline function combine(a:EnumValue, b:EnumValue):String {
return Std.string(a) + ":" + Std.string(b);
}
Of course that can be written smaller using String interpolation:
static inline function combine(a:EnumValue, b:EnumValue):String {
return '$a:$b';
}
Of course that can be 'more dynamic' using type parameters:
static inline function combine<A, B>(a:A, b:B):String {
return '$a:$b';
}
There is totally no need to use Dynamic as suggested. If you use Dynamic, you basically turn off the type system.
live example:
http://try.haxe.org/#a8844
Use Dynamic instead of Enum or pass them as Strings right away since you can always convert to enum from String if you need it later.
Anyway pass the enum as enum:Dynamic and then call Std.string(enum);
EDIT: Using EnumValue is definitely better approach than Dynamic, I use Dynamic in these functions because I send more than just Enums there and I am not worried about type safety in that case.

How to return a vector of objects to managed code efficiently?

I have a ref class that contains a pointer to an unmanaged class. the class has some basic types and also a vector of objects of another class. I would like to know the best way to get and set the vector from managed code. Will a memcpy between unmangedb objects be efficient or setting each member variable of unmanagedb?
for ex (assume the class is complete. I am writing what is relevant to the question)
Assume we already have a managed wrapped for struct UnmanagedB called B.
struct UnmanagedA
{
int a;
vector<UnmanagedB> list;
};
public ref class A : public System::IDisposable
{
public:
// properties
property System::UInt32 a
{
System::UInt32 get();
void set(System::UInt32 value);
}
property array<B^>^ list
{
System::array<B^>^ get(); // what is the best way to set and get the vector
void set(array<B^>^ value);
}
private:
UnmanagedA* obj1;
};
This obviously won't be cleanly possible, since UnmanagedA contains a vector of UnmanagedB values, while A exposes an property of type array<B^>. If this is intended and not a typo, you will need to marshall the content of B^ into instances of UnmanagedB. Otherwise, let UnmanagedA hold a std::vector< B* > and take care of proper lifetime management.

Locking to modify static value-type member. Is it necessary?

I have a CacheHelper class to facilitate interaction with the cache. I want to use a static int field to specify my cache timeout. The field is initially set to a const default value but I want to provide a way for the application to change the default timeout value.
Do you need to lock when modifying a static value type? Is the lock in the setter necessary? Are there any other problems you can see here? Sorry, I'm still pretty dumb when it comes to multithreading.
Thanks.
public static class CacheHelper
{
private static object _SyncRoot;
private static int _TimeoutInMinutes = CacheDefaults.TimeoutInMinutes;
public static int TimeoutInMinutes
{
get
{
return _TimeoutInMinutes;
}
set
{
lock (_SyncRoot)
{
if (_TimeoutInMinutes != value)
{
_TimeoutInMinutes = value;
}
}
}
}
public static void Insert(string key, Object data)
{
if (HttpContext.Current != null && data != null)
{
HttpContext.Current.Cache.Insert(key, data, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(CacheHelper.TimeoutInMinutes));
}
}
}
You could use a volatile variable instead... but you need something, otherwise it's possible that a value written by one thread would never be seen by another.
Note that for "larger" types such as double or long you really should use a lock or the Interlocked class, as modifications to those values may not be atomic.
You don't need to lock here if the client of CacheHelper does somthing like
CacheHelper.TimeoutInMinutes = input.Value;
Since it doesn't rely on the previous value.
If your client does something like
CacheHelper.TimeoutInMinutes += input.Value;
Then you'll need to do some locking
.

Can extension methods modify extended class values?

I was just trying to code the following extension method:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace _4Testing
{
static class ExtensionMethods
{
public static void AssignMe(this int me, int value)
{
me = value;
}
}
}
But it is not working, i mean, can I use an extension method to alter values from extended classes? I don't want to change void return type to int, just changing extended class value. Thanks in advance
Your example uses int, which is a value type. Classes are reference types and behaves a bit differently in this case.
While you could make a method that takes another reference like AssignMe(this MyClass me, MyClass other), the method would work on a copy of the reference, so if you assign other to me it would only affect the local copy of the reference.
Also, keep in mind that extension methods are just static methods in disguise. I.e. they can only access public members of the extended types.
public sealed class Foo {
public int PublicValue;
private int PrivateValue;
}
public static class FooExtensions {
public static void Bar(this Foo f) {
f.PublicValue = 42;
// Doesn't compile as the extension method doesn't have access to Foo's internals
f.PrivateValue = 42;
}
}
// a work around for extension to a wrapping reference type is following ....
using System;
static class Program
{
static void Main(string[] args)
{
var me = new Integer { value = 5 };
int y = 2;
me.AssignMe(y);
Console.WriteLine(me); // prints 2
Console.ReadLine();
}
public static void AssignMe(this Integer me, int value)
{
me.value = value;
}
}
class Integer
{
public int value { get; set; }
public Integer()
{
value = 0;
}
public override string ToString()
{
return value.ToString();
}
}
Ramon what you really need is a ref modifier on the first (i.e. int me ) parameter of the extension method, but C# does not allow ref modifier on parameters having 'this' modifiers.
[Update]
No workaround should be possible for your particular case of an extension method for a value type. Here is the "reductio ad absurdum" that you are asking for if you are allowed to do what you want to do; consider the C# statement:
5.AssignMe(10);
... now what on earth do you think its suppose to do ? Are you trying to assign 10 to 5 ??
Operator overloading cannot help you either.
This is an old post but I ran into a similar problem trying to implement an extender for the String class.
My original code was this:
public static void Revert(this string s)
{
char[] xc = s.ToCharArray();
s = new string(xc.Reverse());
}
By using the new keyword I am creating a new object and since s is not passed by reference it will not be modified.
I changed it to the following which provides a solution to Ramon's problem:
public static string Reverse(this string s)
{
char[] xc = s.ToCharArray();
Array.Reverse(xc);
return new string(xc);
}
In which case the calling code will be:
s = s.Reverse();
To manipulate integers you can do something like:
public static int Increment(this int i)
{
return i++;
}
i = i.Increment();

Resources