Rick Goldstein

Greenhorn
+ Follow
since Oct 10, 2003
Merit badge: grant badges
For More
Cows and Likes
Cows
Total received
0
In last 30 days
0
Total given
0
Likes
Total received
0
Received in last 30 days
0
Total given
0
Given in last 30 days
0
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Rick Goldstein

Guess JNI isn't that interesting ...

For the benefit of anyone else who's doing this kind of thing, thought I'd reply to my own post with what we ended up doing.

We're using JNA, which is a very nifty solution for this particular problem. For the fairly simple set of methods we need to access, it is a very elegant (not to mention very easy to implement) wrapper.

-Rick
16 years ago
Hello,

I'm new to JNI. I have been given an assignment (not for homework--this is real life) to create a Java wrapper API for an existing C API. The C API is currently deployed only on Windows, but versions exist for Linux/Unix platforms, so the solution should be, as much as possible, portable.

I've skimmed through a number of online tutorials and references, but I am having a difficult time discerning a "best practice" for certain things, and I can't find references at all for certain of my issues. Any pointers to books or web sites would be appreciated, as would your own wisdom.

Here are a few of the questions I have (with the answers I have come up with, where I have a glimmer of an idea):

1. Standard mapping of primitive C types to Java. Some are easy--32 bit signed int maps to the Java int type in an obvious way, but some are more difficult. In particular, for an unsigned int, should I use a Java long to capture the full range of values available to a uint, or should I use a "wrapper object" to hold the 4-bytes and provide appropriate accessor methods for the rare cases where I need the value (the C API uses uint mainly for handles to objects it keeps in memory, so the value is unimportant).

2. Mapping 'char *' arguments to StringBuffer. Where the C API uses 'char *' argument to return a (null-terminated) array of characters, I believe the Java side should pass a StringBuffer. Is this correct?

3. Other pointer-to-primitive return values. The C API also uses pointers to primitives to return values to the caller. StringBuffer is a convenient type for null-terminated character arrays, but what about 'int *' or other pointer types? Should I write a class called something like IntegerHolder that can be populated using a field-accessor in the native code? Is there a better way?

Oh, and does anyone have any experience using SWIG to generate the JNI code? Does it do a reasonable job?

I think that's it for now. Thanks for any advice you can provide.

Best,
Rick
16 years ago
I think the problem here is that String objects are immutable. When you assign a new value to the String variable, you are creating a brand new object reference. The array points to the original object reference.

Are you using Java 5? If so, you could make the days of the week a typesafe enum. You could then even encode day-of-week specific behavior on the enumerated values themselves. That seems like it would be more fun.

Cheers,
Rick Goldstein
17 years ago
If all the checks to see if a match is found are performed on the summaryPageDetails object, then I'd move the entire contents of the loop into a method on that class.

Then, make each method into a class of its own with a common method call, like public boolean doesRowMatch(...), with whatever arguments are appropriate. Loop through a collection of instances of these classes, calling doesRowMatch() on each instance until one of them matches. You can even make these processor into inner classes so they have access to common data of the caller.

Does that make sense?

Rick
[ November 29, 2005: Message edited by: Rick Goldstein ]
18 years ago
The issue is not whether the value is in range, it's whether the cast results in loss of information. Truncating a double to a float removes (less significant) bits that contain information. Implicitly casting an int literal that is within the range expressed by the signed byte type only removes "place holder" high-order bits that contain no information. In other words, a 1-byte value of 5 is *exactly equal in value to* a 4-byte value of 5. Not so with float and double. The implicit cast in the other direction (from float to double) is no problem, because the values before and after the cast are identical.

Does that help?

Rick
18 years ago
I note that in the final conditional (the if (...) on the next to last line) you are using = (assignment), rather than == (comparison). Could that be the problem?

Also, why not use the split() function of String?

Rick
18 years ago

Originally posted by Stefan Wagner:
Car or boat - which is better and why?



I don't think this is an apt metaphor. For-loops and while-loops are more isomorphic than cars and boats. As demonstrated, you can pretty much use them interchangeably if you structure the code properly. There are definitely things you can do with cars that you can't do with boats, and vice versa.

The choice between the two kinds of loops is mostly a matter of style. I have known people who always use one or the other, but not both. Personally, I typically use for-loops when the number of iterations is known before the loop starts to execute. For instance, I will use 'for' when I am doing operations on a Collection that must be done on every member. (With Java 5, this is actually even better done with the new for-each construct.)

I am more likely to use 'while' if I can't compute the number of iterations in advance. A good example here is when you are processing an arbitrary stream of data and you want to exit the loop when a certain condition is met.

I don't think my way is better than any other, but it reflects the way I think about loop control structures. Because I follow this style consistently, it is easier for me to understand when coming back to code after some time.

Just my 2 cents.

Best,
Rick
18 years ago
I've been learning guitar for the past couple of years (nothing more painful than trying to learn your first musical instrument when you're near 40, let me tell you), so I've picked up a little about chord theory. Here's my take, for what it's worth.

The chord structure is transposable. In other words, a major chord always has the same chromatic spacing of the notes, which correspond to the I-III-V degrees of the 8 note major scale. For a minor chord, the third is flatted. You could define a Chord class with a type (that could be an enum, if you're using Java 5, or a typesafe enumeration pattern of standard classes, if Java 1.4 or earlier). The type could be some kind of patterned string, or an array of integers, representing the chromatic note numbers for the type. So for a major, it would be (1, 5, 8). Then you just need to provide the root note, and the Chord instance can compute the notes (using an indexed lookup, or something). Even better, provide the chord with a scale (major, minor, Ionian, whatever) and the degree pattern for the chord type, and the root note. Everything is computable from there, without a case statement.

You can do all of this with enums/constants. Never use a literal string in your code if you can help it.

Rick
18 years ago
We're trying really hard to help. I have given you a lot of hints. Seems like the style here is to try not to explicitly give the answers to homework problems. Once again:

1. Look at the getXXX methods of the Distances class.
2. Look at the add() method of the Distances class.

THINK about what you are trying to do, and how that relates to 1) and 2) above.

Rick
18 years ago
Note that your Distances class has a lovely set of accessor methods (getXXX). Note their return types. Think about what you are actually trying to add together. Also note that Distances has an add() method--you might think about whether that would be useful.

Also, don't forget to carefully check your convertXXX methods. The computations are not correct. There are several other problems with your Distances class, which you will probably discover eventually. Was Distances provided as part of the problem, or did you write it yourself? Perhaps you were intended to debug it?

Rick

[ April 01, 2005: Message edited by: Rick Goldstein ]
[ April 01, 2005: Message edited by: Rick Goldstein ]
18 years ago
And when you're done with that, I just noticed that you might want to look at your calculations one more time. (Hint: what kind of operation does '%' represent? I don't think it's what you think. And that's not the only mistake.)

Rick

Ed. for punctuation.
[ April 01, 2005: Message edited by: Rick Goldstein ]
18 years ago
Look at what your static convertXXX methods return. Remember that you can only use the '+' operator for numeric types (and only primitive numerics up until Java 5) or Strings.

-Rick
18 years ago
This sounds to me like a plug-in architecture. The key here is that each module program (plug-in) needs to define a common entry point or interface for the main program to access. The common interface might allow the main program to do something like ask the plug-in for its menus (for example). For an example of a very extensive application framework with a plug-in architecture, see Eclipse.

Rick
[ March 31, 2005: Message edited by: Rick Goldstein ]
18 years ago
Or even better, look at the indexOf methods of String (there are two). You might find one of them especially helpful.

Rick
18 years ago
I think this depends on whether the data was written out as an int (32-bit), or as a byte stream. If an int, the byte order is architecture dependent, and you would need to read in the 4 bytes as an int. Then the lower level interaction with the machine takes care of little/big-endianness. If the bytes were written individually (or as a streamed byte array), then they'll be in whatever order they were written.

If the first byte seems to contain random numbers (and it's only supposed to contain 0x00 or 0x80, i.e. zero or 1 in the most significant bit), then the data was probably written as an int (and you're on a little endian machine). In that case, just read the int. If the high order bit is 1, the number will be negative, so that check is trivial. For the low 20 bits, you'll probably want to use a bit mask.

Rick
18 years ago