I'm trying to pass an array of strings from JS to C using Emscripten. I pass my array to C but when I try to deference, it does not work, it raises "index out of bounds". I've tried many different things so I'll post the minimal amount of code that can reproduce the issue (at least on my machine!). I'm sure I missed something...
Basically trying to put a string into an array (of strings) and give that to C for printing (I'm doing other stuff of course). Feel free to change the "gmp_" or "mpz_" to your (that's not the problem).
Javascript:
var nbData = 1;
var nbColPerData = 1;
var data = new Uint32Array(nbColPerData);
data[0] = this.i2wasm(this.mod);
var nBytes = data.length * data.BYTES_PER_ELEMENT;
var dataPtr = Module._malloc(nBytes);
var dataHeap = new Uint8Array(Module.HEAP8.buffer,dataPtr,nBytes);
dataHeap.set(new Uint8Array(data.buffer));
// create array of pointers
var pointers = new Uint32Array(nbData);
for (var i =0; i < pointers.length; i++) {
pointers[i] = dataPtr + i * data.BYTES_PER_ELEMENT;
console.log("pointers["+i+"] = " + pointers[i].toString(16));
}
// create pointer array on the heap
var nPointerBytes= pointers.length * pointers.BYTES_PER_ELEMENT;
var pointerPtr = Module._malloc(nPointerBytes);
var pointerHeap = new Uint8Array(Module.HEAP8.buffer, pointerPtr,nPointerBytes);
pointerHeap.set( new Uint8Array(pointers.buffer));
printIntMatrix(pointerHeap,nbData)
Module._free(pointerHeap.byteOffset);
Module._free(dataHeap.byteOffset);
i2wasm (hexadecimal string to int array for wasm, works properly):
return allocate(intArrayFromString(integer),'i8',ALLOC_NORMAL);
C code:
void EMSCRIPTEN_KEEPALIVE printInt(char *hex) {
mpz_t n;
mpz_init(n);
printf("printing INT at %p\n",hex);
/////////////////////////////////////
// HERE IT PANICS !
/////////////////////////////////////
printf("printing INT value: %c\n",*hex);
if (mpz_set_str(n,hex,16) != 0) {
printf("hexadecimal invalid");
return;
}
gmp_printf("printInt: %Zd\n",n);
mpz_clear(n);
}
void EMSCRIPTEN_KEEPALIVE printIntMatrix(char **mat, int n) {
printf("printIntMatrix !!\n");
for(int i = 0; i < n; i++) {
printf("matrix[%d] => \n",i);
printf("matrix[%d] => %p\n",i,mat[i]);
printInt(mat[i]);
printf("matrix[%d] => %p DONE\n",i,mat[i]);
}
}
i2wasm() returns char*, so dataPtr is char**.
And _printIntMatrix(pointerHeap, nbData) means _printIntMatrix(pointerHeap | 0, nbData), eventually it is _printIntMatrix(NULL, nbData).
So if printIntMatrix doesn't need char ***mat, _printIntMatrix(dataPtr, nbData); would work.
Related
I am running the following javascript test
var mark = java.lang.System.nanoTime() / 1000000000.0;
for(var i = 0; i != 1000; i++) {
}
var now = java.lang.System.nanoTime() / 1000000000.0;
var e = now - mark;
print(1 / e);
and get this result
27.361456496425802
this seems really slow almost a bug or something i am doing wrong. Here is the java code
try {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("javascript");
String[] lines = IO.readAllLines(IO.file(root, "LoadList.txt"));
String script = "";
for(int i = 0; i != lines.length; i++) {
String file = lines[i].trim();
if(!file.startsWith("#") && file.length() != 0) {
script += IO.readAllText(IO.file(root, file));
}
}
engine.eval(script);
} catch(Exception ex) {
ex.printStackTrace();
}
does anybody know what i am doing wrong or have seen this type of problem and know how to fix if?
Thanks in advance
after doing some research it appears that java's javascript takes a little while to warm up to speed. here is an update to the test
for(var i = 0; i != 1000; i++) {
var mark = java.lang.System.nanoTime() / 1000000000.0;
for(var j = 0; j != 1000; j++) {
}
var now = java.lang.System.nanoTime() / 1000000000.0;
var e = now - mark;
print(1 / e + " fps")
}
and by the last iteration i get 99108.03064699778 fps. (it does vary the lowest one i got, on the last iteration, was around 50000 fps)
I am writing a program in both C and Javascript (on node.js), using ffi, ref, and a few other ref- packages.
I have the following code, which I compile into a library libfun.so:
fun.c
#include "fun.h"
#include <stdio.h>
#include <stdlib.h>
void fill_array(void **data_array, int length)
{
int i;
for (i = 0; i < length; i++) {
data_array[i] = malloc(sizeof(data));
((data *)data_array[i])->id = 256;
((data *)data_array[i])->message = 512;
}
}
void print_array(void **data_array, int length)
{
int i = 0;
for (i = 0; i < length; i++) {
printf("(%d, %d)\n", ((data *)data_array[i])->id,
((data *)data_array[i])->message);
}
}
fun.h
#ifndef fun_h__
#define fun_h__
typedef struct {
int id;
int message;
} data;
void fill_array(void **,int);
void print_array(void **,int);
#endif
fun.js
var ffi = require('ffi');
var Struct = require('ref-struct');
var ref = require('ref');
var ArrayType = require('ref-array');
// js analog of the data struct from fun.h
var Data = Struct({
id: ref.types.int,
message: ref.types.int,
});
// js analog of the type data *
var DataPointer = ref.refType(Data);
// pvoid is the js analog of void * in C
var pvoid = ref.refType(ref.types.void);
var PVoidArray = ArrayType(pvoid);
// set up our foreign functions from libfun
var libfun = ffi.Library('./libfun', {
'fill_array' : ['void', [PVoidArray,ref.types.int]],
'print_array' : ['void', [PVoidArray, ref.types.int]]
});
var myArray = new PVoidArray(10);
libfun.fill_array(myArray,10);
libfun.print_array(myArray,10); // this prints the array of structs correctly, from the C side
My question is: how can I print the array of structs from the Javascript side? I want to pass myArray in as a PVoidArray. I do not want to create an array of structs (i.e. create var DataArray = ArrayType(DataPointer), and use that instead of PVoidArray everywhere).
Let's start with myArray[0]. Can we use our variable Data to (in a flexible way) take myArray[0] and make a struct? Like some function bufferToArray(myArray[0],Data) == a Data instance containing the data of myArray[0].
Looking at the documentation for ref.get(), you could use that:
ref.get(myArray.buffer, index, DataPointer).deref()
will return an instance of Data from index of myArray.
I am trying to create a function that takes 4 parameters and spits out a random number. But I want it so if the same 4 parameters are input, you will always get the same answer. The number should be between 0 and the max argument.
function random (x,y,z,max) {
output = ;
return Math.floor(output * max);
}
Is there any simple forumala I can use to get this? I tried to create one but it didn't look random at all, and would look very similar if you changed one parameter very slightly. I want it to be completely different, but repeatable.
hash function:
function hash (input){
input = 'random'+input;
var hash = 0;
if (input.length == 0) return hash;
for (i = 0; i < input.length; i++) {
char = input.charCodeAt(i);
hash = ((hash<<5)-hash)+char;
hash = hash & hash; // Convert to 32bit integer
}
return Math.abs(hash);
}
Generating an apparently unpredictable data from another is called "hashing"; restricting it to a range is called "modulo". Here is an easy way to do hashing using exponentiation:
const hashLim = () => {
const args = Array.prototype.slice.call(arguments);
const limit = args.shift();
var seed = limit - 1;
for (a in args) {
seed = Math.pow(args[a] + limit, seed) % limit
}
return seed;
}
document.write(hashLim(100, 4, 16, 64) + '<br/>')
document.write(hashLim(100, 5, 16, 64))
You can use some self made calculation for pseudo random values, like this example with pi and the taking of only the fractal part.
function Random(seed) {
var r = seed;
this.random = function () {
var v = r * Math.PI;
r = v - (v | 0);
return r;
}
this.random();
}
var i,
q = new Random(42),
r = new Random(42);
for (i = 0; i < 10; i++) {
document.write(q.random() +'<br>'+ r.random() + '<hr>');
}
I'm working with a system that integrates a Point of Sell (POS) device, I use chrome serial to scan ports and be able to read credit card data.
The problem I'm facing is that I need to concat the LRC from a string in this format:
STX = '\002' (2 HEX) (Start of text)
LLL = Length of data (doesn't include STX or ETX but command).
Command C50 {C = A message from PC to POS, 50 the actual code that "prints" a message on POS}
ETX = '\003' (3 HEX) (End of text)
LRC = Longitudinal Redundancy Check
A message example would be as follows:
'\002014C50HELLO WORLD\003'
Here we can see 002 as STX, 014 is the length from C50 to D, and 003 as ETX.
I found some algorithms in C# like this one or this one and even this one in Java, I even saw this question that was removed from SO on Google's cache, which actually asks the same as I but had no examples or answers.
I also made this Java algorithm:
private int calculateLRC(String str) {
int result = 0;
for (int i = 0; i < str.length(); i++) {
String char1 = str.substring(i, i + 1);
char[] char2 = char1.toCharArray();
int number = char2[0];
result = result ^ number;
}
return result;
}
and tried passing it to Javascript (where I have poor knowledge)
function calculateLRC2(str) {
var result = 0;
for (var i = 0; i < str.length; i++) {
var char1 = str.substring(i, i + 1);
//var char2[] = char1.join('');
var number = char1;
result = result ^ number;
}
return result.toString();
}
and after following the Wikipedia's pseudocode I tried doing this:
function calculateLRC(str) {
var buffer = convertStringToArrayBuffer(str);
var lrc;
for (var i = 0; i < str.length; i++) {
lrc = (lrc + buffer[i]) & 0xFF;
}
lrc = ((lrc ^ 0xFF) + 1) & 0xFF;
return lrc;
}
This is how I call the above method:
var finalMessage = '\002014C50HELLO WORLD\003'
var lrc = calculateLRC(finalMessage);
console.log('lrc: ' + lrc);
finalMessage = finalMessage.concat(lrc);
console.log('finalMessage: ' + finalMessage);
However after trying all these methods, I still can't send a message to POS correctly. I have 3 days now trying to fix this thing and can't do anything more unless I finish it.
Is there anyone that knows another way to calculate LRC or what am I doing wrong here? I need it to be with Javascritpt since POS comunicates with PC through NodeJS.
Oh btw the code from convertStringToArrayBuffer is on the chrome serial documentation which is this one:
var writeSerial=function(str) {
chrome.serial.send(connectionId, convertStringToArrayBuffer(str), onSend);
}
// Convert string to ArrayBuffer
var convertStringToArrayBuffer=function(str) {
var buf=new ArrayBuffer(str.length);
var bufView=new Uint8Array(buf);
for (var i=0; i<str.length; i++) {
bufView[i]=str.charCodeAt(i);
}
return buf;
}
Edit After testing I came with this algorithm which returns a 'z' (lower case) with the following input: \002007C50HOLA\003.
function calculateLRC (str) {
var bytes = [];
var lrc = 0;
for (var i = 0; i < str.length; i++) {
bytes.push(str.charCodeAt(i));
}
for (var i = 0; i < str.length; i++) {
lrc ^= bytes[i];
console.log('lrc: ' + lrc);
//console.log('lrcString: ' + String.fromCharCode(lrc));
}
console.log('bytes: ' + bytes);
return String.fromCharCode(lrc);
}
However with some longer inputs and specialy when trying to read card data, LRC becomes sometimes a Control Character which in my case that I use them on my String, might be a problem. Is there a way to force LRC to avoid those characters? Or maybe I'm doing it wrong and that's why I'm having those characters as output.
I solved LRC issue by calculating it with the following method, after reading #Jack A.'s answer and modifying it to this one:
function calculateLRC (str) {
var bytes = [];
var lrc = 0;
for (var i = 0; i < str.length; i++) {
bytes.push(str.charCodeAt(i));
}
for (var i = 0; i < str.length; i++) {
lrc ^= bytes[i];
}
return String.fromCharCode(lrc);
}
Explanation of what it does:
1st: it converts the string received to it's ASCII equivalent (charCodeAt()).
2nd: it calculates LRC by doing a XOR operation between last calculated LRC (0 on 1st iteration) and string's ASCII for each char.
3rd: it converts from ASCII to it's equivalent chat (fromCharCode()) and returns this char to main function (or whatever function called it).
Your pseudocode-based algorithm is using addition. For the XOR version, try this:
function calculateLRC(str) {
var buffer = convertStringToArrayBuffer(str);
var lrc = 0;
for (var i = 0; i < str.length; i++) {
lrc = (lrc ^ buffer[i]) & 0xFF;
}
return lrc;
}
I think your original attempt at the XOR version was failing because you needed to get the character code. The number variable still contained a string when you did result = result ^ number, so the results were probably not what you expected.
This is a SWAG since I don't have Node.JS installed at the moment so I can't verify it will work.
Another thing I would be concerned about is character encoding. JavaScript uses UTF-16 for text, so converting any non-ASCII characters to 8-bit bytes may give unexpected results.
If I want to read from the input stream in C I write scanf., Is there equivalent method in NodeJS to do the same?
For example, here's the code in C
int n,
m,
i;
scanf("%d", &n);
for (i = 0; i < n; i++) {
scanf("%d", &m);
............
}
Here's where I'm starting from in Node... TODO indicates where I'm stuck:
process.stdin.resume();
process.stdin.setEncoding("ascii");
process.stdin.on("data", function (input) {
var n = +input;
for (var i = 0; i < n; i++) {
// TODO
}
});
For starters, calling scanf and the data event for a readable stream in NodeJS are not equivalent. In the NodeJS example, you will need to parse the chunk of the input you've received.
You can examine how these chunks are sent to you by replacing the body of your on method with a simple:
process.stdout.write('onData: ' + input + '\n');
Given how input then contains your data you'll need to use some method to extract the string of interest and then use parseInt. Perhaps a naive approach to your problem, assuming 1 integer per input:
var n = 0;
var m = 0;
var state = 0;
process.stdin.on('data', function (input) {
switch (state)
{
case 0:
// we're reading 'n'
n = parseInt(input.trim(), 10);
state++;
break;
default:
// we're reading 'm'
m = parseInt(input.trim(), 10);
if (state++ == n)
{
// we've read every 'm'
process.exit();
}
break;
}
});
I'm not a terribly large fan of this means of getting data to your NodeJS event loop, you should instead look to command line arguments, configuration/input files, or some other means.
Check sget.
var sget = require('./sget');
var width = sget('Width?'),
height = sget('Height?'),
area = width * height;
console.log('Area is', area);
This function will do what you asked for:
function readNums(s) {
// Split it up into numbers and spaces
var array = s.split(/(\d+)/);
// Keep just the numbers
array = array.filter(function(i) {return "" + +i == i});
// Convert back to a number
array = array.map(function(i) {return +i});
// How many elements should there have been?
var maxLen = array.shift();
if (array.length < maxLen) {
throw "Not enough enough numbers";
} else {
array.length = maxLen;
}
return array;
}
console.log(readNums("4 10 20 30 40 50 60 70"));
Result:
[10, 20, 30, 40]