I want to create a renderscript in android where an array is passed to the .rs file. On these values some calculation is done and sent back to the user.
I have very little understanding of renderscript, so what I have written might be completely wrong also. Please help me with it.
Android activity
public class RenderTemp extends Activity {
private RenderScript mRS;
private ScriptC_snow mScript;
int[] indices;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.render);
indices = new int[2];
indices[0] = 1;
indices[1] = 2;
createScript();
}
private void createScript() {
mRS = RenderScript.create(this);
Allocation mIN = Allocation.createSized(mRS, Element.I32(mRS), indices.length);
mIN.copyFrom(indices);
mScript = new ScriptC_snow(mRS);
mScript.forEach_root(mIN);
mIN.copyTo(indices);
}
}
snow.rs
#pragma version(1)
#pragma rs java_package_name(#package name)
int32_t *mIN;
void __attribute__((kernel)) root(int32_t in)
{
in = in + 2;
}
Modifying "in" inside your kernel won't cause anything to get updated. You can change it such that your root() function has a return value of int32_t as well. Then do "return in + 2;". Finally, you can pass mIN for both input and output to the forEach (so "mScript.forEach_root(mIn, mIn);"). Even though this will work for you, I would strongly advocate that you separate the input and output Allocations for any real work, as aliasing input/output like this can prevent compiler optimizations for more complex code.
Related
My native code is
typedef struct driver_config {
unsigned int dllVersion;
unsigned int channelCount;
unsigned int reserved[10];
ChannelConfig channel[64];
} DriverConfig;
In Java my class looks like this
public class DriverConfig extends Structure {
public int dllVersion;
public int channelCount;
public int[] reserved= new int[10];
ChannelConfig[] channel = new ChannelConfig[64];
public DriverConfig() {
super();
init();
}
private void init() {
for (int i = 0; i < channel.length; i++) {
channel[i]= new ChannelConfig();
}
}
#Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "dllVersion", "channelCount", "reserved" });
}
//toString()...
}
The method declaration is
int getDriverConfig(DriverConfig driverConfig);
I tried to access the method like this
DriverConfig driverConfig = new DriverConfig();
status = dll.INSTANCE.getDriverConfig(driverConfig);
System.out.println("DriverConfig Status: " + status);
System.out.println(driverConfig.toString());
If channel.length is replaced with less then 50 the array is initialized correctly but with channel.length it did not work. It even did not show any error just nothing.
Your getFieldOrder() array does not include the last element (channel) of your structure. I see in your comments that you attempted to do this but received an error because you have not declared it public. All elements of your structure must be listed in the FieldOrder and also declared public so they can be found with reflection.
Also, with JNA 5.x (which you should be using) the #FieldOrder annotation is preferred.
You haven't identified the mapping for ChannelConfig, but your question title and this API link matching your structure indicate that it is a nested structure array. Structure arrays must be allocated using contiguous memory, either by directly allocating the native memory (new Memory()) which requires knowing the structure size, or by using Structure.toArray(). Allocating in a loop as you have done will end up with memory for each new structure allocated at possibly/probably non-contiguous locations in native memory. Given that you state that it appears to work for some values, you might be getting lucky with contiguous allocations, but your behavior is certainly undefined.
Your structure mapping should therefore be:
#FieldOrder ({"dllVersion", "channelCount", "reserved", "channel"})
public class DriverConfig extends Structure {
public int dllVersion;
public int channelCount;
public int[] reserved= new int[10];
public ChannelConfig[] channel = (ChannelConfig[]) new ChannelConfig().toArray(64);
}
I have got a Java memory puzzle from internet and trying hard to understand it, and what I understood till now is that Java is releasing memory of object with ended life on initialization of new object, though I am unable to get any proof on the same. If any one have any idea on it please guide.
Puzzle is as below
private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6);
public void f()
{
{
byte[] data = new byte[dataSize];
}
//int i = 0; //If uncommented then program work fine
byte[] data2 = new byte[dataSize];
}
In Android Studio, I have two array lists with a custom object
ArrayList<MenuMaker> consessionlist = new ArrayList<MenuMaker>();
ArrayList<MenuMaker> entrylist = new ArrayList<MenuMaker>();
And have a few voids that depending on which mode we are in, it needs to use one ArrayList or the other:
private void createMenuButtons()
{
int FoodSize = consessionlist.size();
...
I realize I could do an if statement that if mode = 0 use consessionlist, else use entrylist, but is there a way to say
private void setmode(mode)
{
if (mode == 0){
menulist = consessionlist;
}
else
{
menulist = entrylist;
}
}
private void createMenuButtons()
{
int FoodSize = menulist.size();
...
*Pass-by-reference vs pass-by-value seem to kick my butt on the Oracle test.
I thought I would have to use an if statement overtime I need to choose or have to add some weird complexity, but thus far its actually working as I wanted it to.
Im trying to make a fun application that will take a sound file and modify it, and create a new sound file.
One of the things I am trying to do is make the sound file twice as long. So I essentially make a new array that goes {2,2,3,3,7,7,8,8} instead of the original {2,3,7,8}. I am using doubles, this is simply an example
I want the original array (samples) to now reference the start of the array I just created (temp) so when the file saves it now save the temp array.
I can increase or decrease the volume of the music file no problem, and save it as such. I omitted that part of the code as it is not pertinent here.
If anyone is kind enough to help me, I also want to know the why behind it
public class Sound {
double[] samples;
//So we only have to declare it once. Reference to an array
public Sound() {
//This constructor should initialize the samples array to be empty
samples = new double[0];
//Initialize an array with nothing because we will be using that to reference the
//location of other arrays
}
public void wavRead(String fileName) {
samples = WavIO.read(fileName);
//Samples was an adress of an array we set to 0. Then we used WavIO to create an aray of doubles, now
//we tell samples to reference this new address over here. Samples has the addsss of the new array
}
public void wavSave(String fileName) {
WavIO.write(fileName, samples);
}
public void lengthen() {
double[] temp = new double[(samples.length *2)];
int t = 0;
for(int i = 0; i < samples.length; i++) {
//Set a variable to increase the temp array by
temp[t] = samples[i];
//Have position 0 of temp = position 0 of soundRaw
t++;
//Increase the position in the temp array by one
temp[t] = samples[i];
//Have position 1 of temp array = position 0 of soundRaw
}
samples[0] = temp;
//Here is where I try and have the samples array reference the start of another array. I tried multiple things, this is simply the last effort I tried
}
And here is the application I am using to test the code
public class App {
public static void main(String[] args) {
Sound s = new Sound();
//We are now calling the other code
s.wavRead("bye8");
//If you want to mess with your own .wav file, replace this name
s.lengthen();
s.wavSave("bye8New");
}
}
Replacing this code line
samples[0] = temp;
with just
samples = temp;
will suffice! :)
Use a DoubleBuffer, it is much easier to do what you want to achieve.
To create a new DoubleBuffer which is... Double... The size and duplicates, you'll then do:
// Important!
origBuf.rewind();
final DoubleBuffer newBuf = DoubleBuffer.allocate(origBuf.remaining() * 2);
double value;
while (origBuf.hasRemaining()) {
value = origBuf.get();
newBuf.put(value).put(value);
}
Then newBuf.array() will return the double[] array "with duplicates".
Also note that a DoubleBuffer, like any XBuffer, allows you to set endianness.
Just use samples=temp; instead of samples[0] = temp;!
How to interact with the Windows API using Java and the JNA (Java Native Access)?. I'm trying to make the mouse do something by queuing a mouse event on the mouse input stream, and the code works, in that the SendInput(...) method returns 1 suggesting that it has successfully queued the event, but yet the mouse itself does nothing.
My SSCCE:
Edit: edited to fill in the dwFlags field. I've tried several combinations of constants either by themselves or bit-or combined without success still. Again, the SendInput method returns 1 as it should suggesting a functioning method, but the mouse doesn't budge:
import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinDef.*;
import com.sun.jna.platform.win32.WinUser.*;
import com.sun.jna.win32.StdCallLibrary;
public class MouseUtils {
public interface User32 extends StdCallLibrary {
public static final long MOUSEEVENTF_MOVE = 0x0001L;
public static final long MOUSEEVENTF_VIRTUALDESK = 0x4000L;
public static final long MOUSEEVENTF_ABSOLUTE = 0x8000L;
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
DWORD SendInput(DWORD dWord, INPUT[] input, int cbSize);
}
public static void main(String[] args) {
INPUT input = new INPUT();
input.type = new DWORD(INPUT.INPUT_MOUSE);
input.input.mi.dx = new LONG(500);
input.input.mi.dy = new LONG(500);
input.input.mi.mouseData = new DWORD(0);
input.input.mi.dwFlags = new DWORD(User32.MOUSEEVENTF_MOVE
| User32.MOUSEEVENTF_VIRTUALDESK | User32.MOUSEEVENTF_ABSOLUTE);
// input.input.mi.dwFlags = new DWORD(0x8000L);
input.input.mi.time = new DWORD(0);
INPUT[] inArray = {input};
int cbSize = input.size(); // mouse input struct size
DWORD nInputs = new DWORD(1); // number of inputs
DWORD result = User32.INSTANCE.SendInput(nInputs , inArray, cbSize);
System.out.println("result: " + result); // return 1 if the 1 event successfully inserted
}
}
Edit 2:
Doing more reading, and it seems that my understanding of arrays with JNA is deficient, that I have to think in terms of C arrays where an array is simply a pointer to a region of contiguous memory. More to come (I hope!).
JNA document Using Structures And Unions reads:
Unions are generally interchangeable with Structures, but require that you indicate which union field is active with the setType method before it can be properly passed to a function call.
I guess you missed setType part. Also, when using MOUSEEVENTF_ABSOLUTE, dx and dy are specified as the coordinate of the mouse, not pixels.
Following works:
public interface User32 extends StdCallLibrary {
...
public static final int SM_CXSCREEN = 0x0;
public static final int SM_CYSCREEN = 0x1;
int GetSystemMetrics(int index);
}
public static void main(String[] args) {
...
input.input.setType("mi");
input.input.mi.dx = new LONG(500 * 65536 / User32.INSTANCE.GetSystemMetrics(User32.SM_CXSCREEN));
input.input.mi.dy = new LONG(500 * 65536 / User32.INSTANCE.GetSystemMetrics(User32.SM_CYSCREEN));
...
}
Call the toArray() method on your structure to obtain a contiguous block of memory.
INPUT input = new INPUT();
INPUT[] arg = (INPUT[])input.toArray(1);
Alternatively, you can simply declare an alternate method mapping for SendInput:
DWORD SendInput(int nInputs, INPUT pInputs, int cbSize);
However, there may be something else going on (permissions, perhaps? see MS notes on UIPI), since your example ought to work (at least with a single array element).
EDIT: the Union.setType() answer is indeed the correct one.
input.input.mi.dwFlags = new DWORD(0);
You didn't specify any of the mouse input flags, so there was no mouse input.