How to pass a callback to EM_ASM for c++? - c++

I do not know how to pass the value asynchronously to EM_ASM, here's how I try to do it (but JS says it's not a function):
const auto testFunc = [] (const char* data)
{
printf("data: %s\n", data);
}
EM_ASM_(
{
var funcResult = ($0);
var text = "data";
var lengthBytes = lengthBytesUTF8(text) + 1;
var stringOnWasmHeap = _malloc(lengthBytes);
stringToUTF8(text, stringOnWasmHeap, lengthBytes);
// exception thrown: TypeError: funcResult is not a function
funcResult(stringOnWasmHeap);
}, testFunc);
The documentation says that you can use a function (em_str_callback_func) of the em_str_callback_func type. But it doesn't say how to use it.
https://emscripten.org/docs/api_reference/emscripten.h.html

I don't know about passing callbacks, but if what you want to do is to return a value from JS, then the docs have such an example: you have to use EM_ASM_INT instead:
int x = EM_ASM_INT({
console.log('I received: ' + $0);
return $0 + 1;
}, 100);
printf("%d\n", x);
The API reference has another example for returning a string:
char *str = (char*)EM_ASM_INT({
var jsString = 'Hello with some exotic Unicode characters: Tässä on yksi lumiukko: ☃, ole hyvä.';
var lengthBytes = lengthBytesUTF8(jsString)+1;
// 'jsString.length' would return the length of the string as UTF-16
// units, but Emscripten C strings operate as UTF-8.
var stringOnWasmHeap = _malloc(lengthBytes);
stringToUTF8(jsString, stringOnWasmHeap, lengthBytes);
return stringOnWasmHeap;
});
printf("UTF8 string says: %s\n", str);
free(str); // Each call to _malloc() must be paired with free(), or heap memory will leak!
Once you have the value in C you can just call your testfunc directly.

Related

ReadOnlySequence<char> conversion from ReadOnlySequence<byte>?

I'm trying to use System.IO.Pipelines to parse large text files.
But I can't find no conversion function from ReadOnlySequence to ReadOnlySequence. For example like MemoryMarshal.Cast<byte,char>.
IMHO it is pretty useless having a generic ReadOnlySequence<T> if there is only one particular type (byte) applicable.
static async Task ReadPipeAsync(PipeReader reader, IStringValueFactory factory)
{
while (true)
{
ReadResult result = await reader.ReadAsync();
ReadOnlySequence<byte> buffer = result.Buffer;
//ReadOnlySequence<char> chars = buffer.CastTo<char>(); ???
}
}
You would have to write a conversion operator to achieve this cast. You cannot cast it explicitly. Be aware that a char[] is two bytes, so you need to choose your encoding algorithm.
IMHO it is pretty useless having a generic ReadOnlySequence<T> if
there is only one particular type (byte) applicable.
While it's true that System.IO.Pipelines will only give you a ReadOnlySequence<byte> because of the fact that a PipeReader is attached to a Stream which is just a stream of bytes, there are other use cases for a ReadOnlySequence<T> eg,
ReadOnlySequence<char> roChars = new ReadOnlySequence<char>("some chars".ToCharArray());
ReadOnlySequence<string> roStrings = new ReadOnlySequence<string>(new string[] { "string1", "string2", "Another String" });
Your conversion operator would have similar logic to the below, but you would set your encoding appropriately.
static void Main(string[] args)
{
// create a 64k Readonly sequence of random bytes
var ros = new ReadOnlySequence<byte>(GenerateRandomBytes(64000));
//Optionally extract the section of the ReadOnlySequence we are interested in
var mySlice = ros.Slice(22222, 55555);
char[] charArray;
// Check if the slice is a single segment - not really necessary
// included for explanation only
if(mySlice.IsSingleSegment)
{
charArray = Encoding.ASCII.GetString(mySlice.FirstSpan).ToCharArray();
}
else
// Could only do this and always assume multiple spans
// which is highly likley for a PipeReader stream
{
Span<byte> theSpan = new byte[ros.Length];
mySlice.CopyTo(theSpan);
// ASCII Encoding - one byte of span = 2 bytes of char
charArray = Encoding.ASCII.GetString(theSpan).ToCharArray();
}
// Convert the char array back to a ReadOnlySegment<char>
var rosChar = new ReadOnlySequence<char>(charArray);
}
public static byte[] GenerateRandomBytes(int length)
{
// Create a buffer
byte[] randBytes;
if (length >= 1)
randBytes = new byte[length];
else
randBytes = new byte[1];
// Create a new RNGCryptoServiceProvider.
System.Security.Cryptography.RNGCryptoServiceProvider rand =
new System.Security.Cryptography.RNGCryptoServiceProvider();
// Fill the buffer with random bytes.
rand.GetBytes(randBytes);
// return the bytes.
return randBytes;
}

How to get a Java string from a char pointer in C++

I am porting the openvr sample to jogl, after we created the binding with jna.
Almost at the end (before rendering the controllers and the tracking base stations), I got stuck trying to translate a char pointer in C to a String in Java.
C++ code here:
//-----------------------------------------------------------------------------
// Purpose: Helper to get a string from a tracked device property and turn it
// into a std::string
//-----------------------------------------------------------------------------
std::string GetTrackedDeviceString( vr::IVRSystem *pHmd, vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop, vr::TrackedPropertyError *peError = NULL )
{
uint32_t unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty( unDevice, prop, NULL, 0, peError );
if( unRequiredBufferLen == 0 )
return "";
char *pchBuffer = new char[ unRequiredBufferLen ];
unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty( unDevice, prop, pchBuffer, unRequiredBufferLen, peError );
std::string sResult = pchBuffer;
delete [] pchBuffer;
return sResult;
}
GetStringTrackedDeviceProperty here:
/** Returns a string property. If the device index is not valid or the property is not a string type this function will
* return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing
* null. Strings will generally fit in buffers of k_unTrackingStringSize characters. */
virtual uint32_t GetStringTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError = 0L ) = 0;
Where VR_OUT_STRING() is defined here as:
# define VR_CLANG_ATTR(ATTR)
#define VR_OUT_STRING() VR_CLANG_ATTR( "out_string: ;" )
I have already done something similar where I had to call a function that expect the pointer to an array of TrackedDevicePose_t structures:
private TrackedDevicePose_t.ByReference trackedDevicePosesReference = new TrackedDevicePose_t.ByReference();
public TrackedDevicePose_t[] trackedDevicePose
= (TrackedDevicePose_t[]) trackedDevicePosesReference.toArray(VR.k_unMaxTrackedDeviceCount);
I created first the reference and then from it the actual array.
But here I can't have a class extending the char array..
private String getTrackedDeviceString(IVRSystem hmd, int device, int prop, IntBuffer propError) {
int requiredBufferLen = hmd.GetStringTrackedDeviceProperty.apply(device, prop, Pointer.NULL, 0, propError);
if(requiredBufferLen == 0) {
return "";
}
CharArray.ByReference charArrayReference = new CharArray.ByReference();
char[] cs = charArrayReference.toArray(requiredBufferLen);
return null;
}
Where apply (here) is:
public interface GetStringTrackedDeviceProperty_callback extends Callback {
int apply(int unDeviceIndex, int prop, Pointer pchValue, int unBufferSize, IntBuffer pError);
};
CharArray class, crap attempt here
Any ideas?
I've done some porting of C and C++ code to Java, and while it's probably horribly hacky, the best I've come up with to solve cases where a pointer to an int primitive or a char*/String is needed for a function call, is to create a small wrapper class with a single property, pass that object into the function, change the property as needed, and retrieve the new value after the function call. So something like:
public class StringPointer {
public String value = "";
}
StringPointer pchBuffer = new StringPointer();
unRequiredBufferLen = pHmd.GetStringTrackedDeviceProperty( unDevice, prop, pchBuffer, unRequiredBufferLen, peError );
String sResult = pchBuffer.value;
and inside GetStringTrackedDeviceProperty()
...
pchValue.value = "some string";
...
In this case, you can use a String, since that's what your code is doing with the char* after the function call, but if it actually really needs to be a char[], you can just create char[] pchBuffer = new char[unRequiredBufferLen]; and pass that into the function. It will be just like you were using a char* in C++, and any changes you make inside the array will be visible after the function ends, and you can even do String sResult = new String(pchBuffer);.

Convert a string into closure in ColdFusion

I have a very basic question. Is it possible to convert a string into a closure? I tried evaluate() but it didn't work.
evaluate( "myFunction = function(val){ return dollarFormat( val ); }" );
What I have in mind is to save custom functions in the database as string and then run it as needed.
Thank you!
Edit: Just to clarify: I want to be able to save "function(val){ return dollarFormat( val ); }" as a string in database and be able to convert it into a functioning closure.
I would go with user2943775 answer:
<cfscript>
FileWrite("/ram/UDFs.cfm", "<cfset myFunction = function(val){ return dollarFormat( val ); }>")
include template="/ram/UDFs.cfm";
writedump(myFunction(10));
</cfscript>
And in your Application.cfc
component {
this.mappings["/ram"] = "ram://";
...
}
I came across a similar solution, though I was unable to use the in-memory filesystem due to security restrictions. In my Application.cfc, I added the following mapping:
this.mappings = {
"/models" = "#APP_ROOT_PATH#cfcs/models",
"/utils" = "#APP_ROOT_PATH#cfcs/utils",
"/modules" = "#APP_ROOT_PATH#_modules",
"/components" = "#APP_ROOT_PATH#cfcs",
"/udfs" = "#APP_ROOT_PATH#includes/udfs" // path for global (and temporary) UDFs
};
The UDF I created is as follows:
/**
* Takes a string representation of a function and returns it as a Closure
* #output false
* #return Closure
*/
private any function toClosure (required string closure) {
local.id = replace(createUUID(), "-", "", "all");
local.udfpath = "/udfs/udf#id#.cfm";
local.script = "<cfscript>local.fn#id# = #closure#;</cfscript>";
try {
fileWrite(expandPath(udfPath), script);
include udfpath;
} catch (any e) {
} finally {
try {
fileDelete(expandPath(udfPath));
} catch (any e) {}
}
if (!structkeyExists(local, "fn#id#") || !isClosure(local["fn#id#"])) {
throw (message="Unable to compile closure");
}
// return the closure
return local["fn#id#"];
}
And the result:
myFn = toClosure("function (num) { return num + 1; }");
myFn(1); // returns 2

Qt and GoogleMaps - duration type

I use this code to getData from javascript:
const QVariant myvar = this->page()->mainFrame()->
evaluateJavaScript("measureDistance("+QString::fromStdString(prev->marker_id)+","+QString::fromStdString(stop->marker_id+");"));
bool ok;
const int myint = myvar.toInt(&ok);
if (!ok)
qWarning() << "Error getting int from JS";
qDebug() << myint;
getMapTimeDistance(location, QString::fromStdString(prev->getName()), stop, 10);
And in javascript the last line is:
function measureDistance(m1, m2) {
var wp = new Array();
var lstart = new google.maps.LatLng(markers[m1].position);
var lend = new google.maps.LatLng(markers[m2].position);
var request = {
origin : lstart,
destination : lend,
waypoints : [],
optimizeWaypoints: true,
travelMode : google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status== google.maps.DirectionsStatus.OK) {
response.routes[0].legs[0].duration.text;
} else {
document.getElementById('locationD').value = "drawRouteBad";
}
});
}
Do you know why this code won't work for me? I've tried different combinations of types, but nothing helped. Probably I don't know what type is javasscripts value. Maybe I should pass it to the qt in different way?
response.routes[0].legs[0].duration.value; is coming from the Google Maps API v3 Directions Service (per your last question. That service is asynchronous, you can't return anything from the call to it, you have to use any data you need inside the callback function (when it has been returned from the server and is available).

Using string pointers in C++ and Objective-C

I have a sample project here on github where I created a c++ wrapper class for an external C++ library that I want to use in Objective-C.
I don't understand why my returned pointers are sometimes correct and sometimes wrong. Here's sample output:
Test Data = 43343008
In Compress 43343008
Returned Value = 43343008
Casted Value = 43343008
Test Data = 2239023
In Compress 2239023
Returned Value = 2239023
Casted Value = 2239023
Test Data = 29459973
In Compress 29459973
Returned Value = 29459973
Casted Value = l.remote
Test Data = 64019670
In Compress 64019670
Returned Value =
Casted Value = stem.syslog.master
In the above output you can see that the 1st and 2nd click of the button outputs the results I was expecting. In each of the other clicks either the returned value or casted value are invalid. I'm assuming this is because my pointer is pointing to an address I wasn't expecting. when running the app multiple times, any button click could be right or wrong.
I also tried with a single thread but experienced similar results.
The complete code is on github but here are the important bits.
ViewController.m
#import "ViewController.h"
extern const char * CompressCodeData(const char * strToCompress);
#implementation ViewController
...
// IBAction on the button
- (IBAction)testNow:(id)sender
{
[self performSelectorInBackground:#selector(analyze) withObject:nil];
}
- (void)analyze
{
#synchronized(self) {
const char *testData = [[NSString stringWithFormat:#"%d",
(int)(arc4random() % 100000000)] UTF8String];
NSLog(#"Test Data = %s", testData);
const char *compressed = CompressCodeData(testData);
NSLog(#"Returned Value = %s", compressed);
NSString *casted = [NSString stringWithCString:compressed
encoding:NSASCIIStringEncoding];
NSLog(#"Casted Value = %#\n\n", casted);
}
}
#end
SampleWrapper.cpp
#include <iostream>
#include <string.h>
#include <CoreFoundation/CoreFoundation.h>
using namespace std;
extern "C"
{
extern void NSLog(CFStringRef format, ...);
/**
* This function simply wraps a library function so that
* it can be used in objective-c.
*/
const char * CompressCodeData(const char * strToCompress)
{
const string s(strToCompress);
// Omitted call to static method in c++ library
// to simplify this test case.
//const char *result = SomeStaticLibraryFunction(s);
const char *result = s.c_str();
NSLog(CFSTR("In Compress %s"), result);
return result;
}
}
You are returning a pointer to at object that has been deallocated.
const string s(strToCompress);
…
const char *result = s.c_str();
NSLog(CFSTR("In Compress %s"), result);
return result;
s does not exist after CompressCodeData() function is over, so the pointer to it's internal memory is invalid.
You could allocate a chunk of memory to hold the response, but it would be up to the caller to release it.
char *compressed = CompressCodeData(testData);
NSLog(#"Returned Value = %s", compressed);
NSString *casted = [NSString stringWithCString:compressed
encoding:NSASCIIStringEncoding];
free(compressed);
NSLog(#"Casted Value = %#\n\n", casted);
…
const char * CompressCodeData(const char * strToCompress)
…
char *result = strdup(s.c_str());
Another solution is to pass in the memory to store the data into.
char compressed[2048]; // Or whatever!
CompressCodeData(testData, compressed, sizeof(compressed));
NSLog(#"Returned Value = %s", compressed);
NSString *casted = [NSString stringWithCString:compressed
encoding:NSASCIIStringEncoding];
NSLog(#"Casted Value = %#\n\n", casted);
…
void CompressCodeData(const char * strToCompress, char *result, size_t size)
…
s.copy(result, size - 1);
result[s.length() < size ? s.length() : size-1] = '\0';