I've been tasked with converting some code from javascript to C++. While I'm decently familiar with Javascript, I'm pretty inexperienced with C++.
The javascript code heavily makes use of objects. For example the following code is used to convert angles from degrees to any other specified unit:
var allConversions = {
"Angle": {
"degrees": {
"degrees":function(inputNum) { return inputNum*1},
"minutes":function(inputNum) { return inputNum*60},
"radians":function(inputNum) { return inputNum*0.0174532925},
"revolutions":function(inputNum) { return inputNum*0.00277777778},
"seconds":function(inputNum) { return inputNum*3600},
}
}
exports.convertUnits= function(unitType, inUnit, outUnit, inputVal) {
return allConversions[unitType][inUnit][outUnit] (inputVal);
}
I'm wondering what is the best practice for how to create something similar in C++? Should I try and create something similar with a struct or class?
Not exactly sure what all the down votes are about. I see nothing wrong with your question.
JavaScript is a typeless language, and it's a bit... flexible in it's construction of objects. Depending on the actual code, you have two options and you'll want to use a mix of both.
Option 1: Create a Class
In this case, you'd create a class for the specific data structure, with properties for each value you need.
Use this when the JavaScript object is consistent throughout all it's uses.
Option 2: Use a Hash Map
There are a variety of different hash map classes. Which you choose is up to the specific version and framework(s) you're using.
Regardless though, these generally work like a JavaScript object, where you can create key/value pairs. Use this when your not quite sure what you're data will be.
Depends a lot on overall structure and context - that is missing in your code snippet. Probably, a simple class with some inline functions would do. But if I had to attempt an equivalent code as provided, I'd have to write something like this:
someClass.hpp
#ifndef SOMECLASS_H
#define SOMECLASS_H
#include <string>
using std::string;
class degrees
{
public:
double inputVal;
degrees(string, string, string, double); // a constructor
double degreesFunc(double); // double?, can't have same name func
double minutes(double);
double radians(double);
double revolutions(double);
double seconds(double);
};
class Angle : public degrees
{
public:
Angle(string, string, string, double);
};
class allConversions : public Angle
{
public:
allConversions(string, string, string, double);
};
#endif /* SOMECLASS_H */
someClass.cxx
#include "someClass.hpp"
degrees::degrees(
string unitType,
string inUnit,
string outUnit,
double inputVal)
{
this->inputVal = inputVal;
}
double degrees::degreesFunc(double inputNum)
{
return inputNum*1;
}
double degrees::minutes(double inputNum)
{
return inputNum*60;
}
double degrees::radians(double inputNum)
{
return inputNum*0.0174532925;
}
double degrees::revolutions(double inputNum)
{
return inputNum*0.00277777778;
}
double degrees::seconds(double inputNum)
{
return inputNum*3600;
}
//-------------------------------------------------
Angle::Angle(
string a,
string b,
string c,
double d)
: degrees(a, b, c, d) { }
allConversions::allConversions(
string a,
string b,
string c,
double d)
: Angle(a, b, c, d) { }
test.cpp
#include <iostream>
#include "someClass.hpp"
using std::cout;
int main()
{
allConversions convertUnits("what?", "what?", "what?", 10);
cout << convertUnits.inputVal << '\n';
cout << convertUnits.radians(10) << '\n';
cout << convertUnits.minutes(10) << '\n';
}
Compiling with g++ with Makefile:
all:
g++ -c someClass.cxx
g++ -c test.cpp
g++ someClass.o test.o -o run
Run: ./run
Related
I am trying to write a web application that will do sort of word processing (say spell check, grammar check, word analysis) using back-end C/C++ code. (I have got c/C++ code working in another desktop app... I want to bring it to web).
I want an example minimal code doing this (pass array of strings from JavaScript to c/c++ code...c/c++ code will do the word operations... I have this code ......and the resulting array of strings will be sent back to JavaScript where they will be processed further. (passing arrays to and from is important)
Please point me to any such code/tutorial, from where I can make a start.
I searched GitHub. I found several projects using emscripten but could not get this anywhere. (Only place I could get some clue was Hunspell built with emscripten ... however I could not build it successfully)
Please let me know . Thanks in advance.
First prepare the C++ side to receive a string (character array):
static char *string_buffer = NULL;
static size_t string_length = 0;
void EMSCRIPTEN_KEEPALIVE string_start_js(void) {}
void EMSCRIPTEN_KEEPALIVE string_final_js(void) {}
char * EMSCRIPTEN_KEEPALIVE string_ensure(size_t length)
{
// ensure that the buffer is long enough
if (length <= string_length) return string_buffer;
// grow the buffer
char *new_buffer = realloc(string_buffer, length + 1);
// handle the out of memory
if (new_buffer == null) return NULL;
// remember
string_buffer = new_buffer;
string_length = length;
// done
return string_buffer;
}
void EMSCRIPTEN_KEEPALIVE string_handle(size_t length)
{
// sanity
if (string_buffer == NULL || length > string_length) halt;
// terminate
string_buffer[length] = 0;
// work with the string characters, store/process it
}
void EMSCRIPTEN_KEEPALIVE string_clear(void)
{
// friendly
if (string_buffer == NULL) return;
// free
free(string_buffer);
// remember
string_buffer = NULL;
string_length = 0;
}
From the JavaScript side send one string to the C++ side:
let strings = ["abc", "defg", "1"];
// inform the C++ side that some strings are going to be transferred
exports['string_start_js']();
// send all strings
for (var i = 0; i < strings.length; i++)
{
// single string to transport
let string = strings[i];
// convert to a byte array
let string_bytes = new TextEncoder().encode(string);
// ensure enough memory in the C++ side
let string_offset = exports["string_ensure"](string_bytes.byteLength);
// handle the out of memory
if (string_offset == 0) throw "ops...";
// have view of the instance memory
let view = new Uint8Array(memory.buffer, string_offset, string_bytes.byteLength);
// copy the string bytes to the memory
view.set(string_bytes);
// handle
exports['string_handle'](string_bytes.byteLength);
}
// inform the C++ side that all strings were transferred
exports['string_final_js']();
// clear the used buffer
exports['string_clear']();
The way from C++ to WASM can be more simple:
have a character array (pointer) and its length
call an import function to give the array pointer to JavaScript and its length
make a view of the memory
read the characters from the view
Something like this in the C++ side:
extern "C" {
extern void string_start_cpp(void);
extern void string_final_cpp(void);
extern void string_fetch(char *pointer, size_t length);
}
void foo(void)
{
// inform the JavaScript side that
string_start_cpp();
// runtime string
const char *demo = "abc";
// send to JavaScript
string_fetch(demo, strlen(demo));
// inform the JavaScript side all strings were send
string_final_cpp();
}
And in JavaScript supply the functions during the instance creation:
string_start_cpp: function(offset, length)
{
console.log("{");
},
string_final_cpp: function(offset, length)
{
console.log("}");
},
string_fetch: function(offset, length)
{
// view the bytes
let view = new Uint8Array(memory.buffer, offset, length);
// convert the UTF-8 bytes to a string
let string = new TextDecoder().decode(view);
// use
console.log(string);
}
I did not test the code, there could be some syntax errors. You can improve in many places the code, but the idea is what counts.
When I tried to compile the following snippet into WebAssembly binary, I kept hitting the unresolved symbol: llvm_trap warning, which makes the wasm code not consumable from JS.
emcc test.c -s WASM=1 -s ONLY_MY_CODE=1 -s "EXPORTED_FUNCTIONS=['_test']" -O2 -g -o test.js
test.c (This is a test code to reproduce the issue without doing meaningful jobs.)
int test(int *buf) {
int C = 1;
// Assuming WebAssembly.Memory buffer has been preloaed with data.
// *T represents the preloaded data here. And We know *T and *buf
// won't overlap in memory.
int *T = 0;
int index = C ^ buf[5];
int right = T[index];
int left = (unsigned)C >> 8;
// warning disappears if this is commented out. But why?
C = left ^ right;
return C;
}
I didn't write any llvm_trap related code. Does someone have ideas what does it mean?
The variable T must be initialised. If it represents an array that 'maps' to the WebAssembly linear memory, you can define it as a global as follows:
int T[1000];
int test(int *buf) {
int C = 1;
int index = C ^ buf[5];
int right = T[index];
int left = (unsigned)C >> 8;
// warning disappears if this is commented out. But why?
C = left ^ right;
return C;
}
This compiles without the llvm_trap warnings.
For more detail on how to pass data to a WASM function using linear memory, see the following question:
How to access WebAssembly linear memory from C/C++
In c++, reinterpreting the meaning of a bunch of bytes is easy, here's from integer to std::string and back to show what I mean
std::string pack_in_string(int v) {
std::string ret;
ret.reserve(4);
*reinterpret_cast<int*>(const_cast<char*>(ret.c_str())) = v;
return ret;
}
int extract_from_string(std::string str) {
return *reinterpret_cast<const int*>(str.c_str());
}
int main()
{
auto str = pack_in_string(10);
auto val = extract_from_string(str);
std::cout << val;
}
Even though js isn't strictly typed on the surface, AFAIK it internally still differentiates between strings, numbers and objects. I'm interested in packing numbers as 32b ints into strings and vice versa. Can it be done?
i try to get SHA1 working in swift.
without using CommonCrypto since it is not default in swift.
please see https://gist.github.com/wdg/f7c8c4088030c59f0f45 (since it's a little to big to post)
if i run a test case in Xcode:
func test_sha1() {
XCTAssertEqual(sha1("test"), "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3")
}
it will fail, and return 2d891cc96e32c32e8d26704d101208b954f435a5
i got the hash with:
$ php -r "echo sha1('test');echo(PHP_EOL);"
a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
i think the problem is that in the javascript file they use >>> and i don't know what this operator is.
So i have used >>.
i hope someone can help.
Thanks in advance
Use Common Crypto for several reasons: 1. It is correct. 2. It is FIPS 140-2 certified. 3. It is over 1000 times faster than a code based Swift implementation.
Note: Common Crypto uses the hardware encryption engine.
Just add a bridging header with the include:
#import <CommonCrypto/CommonCrypto.h>
Example code for SHA256 (SHA1 should no longer be used):
func sha256(dataIn dataIn:NSData) -> NSData {
let digest: NSMutableData! = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH));
CC_SHA256(dataIn.bytes, CC_LONG(dataIn.length), UnsafeMutablePointer<UInt8>(digest.mutableBytes));
return digest;
}
or
func sha1(dataIn dataIn:NSData) -> NSData {
let digest: NSMutableData! = NSMutableData(length: Int(CC_SHA1_DIGEST_LENGTH));
CC_SHA1(dataIn.bytes, CC_LONG(dataIn.length), UnsafeMutablePointer<UInt8>(digest.mutableBytes));
return digest;
}
or
func sha1(string string: String) -> [UInt8] {
var digest = [UInt8](count: Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
if let data = string.dataUsingEncoding(NSUTF8StringEncoding) {
CC_SHA1(data.bytes, CC_LONG(data.length), &digest)
}
return digest
}
I've got a solution, there was something wrong with the rotate function.
i have changed the rotate function to
func rotate(n: Int, _ s: Int) -> Int {
return ((n << s) & 0xFFFFFFFF) | (n >> (32 - s))
}
and now it works.
I am having quite a lot of problems with emscripten inter-operating between C and Javascript.
More specifically, I am having trouble accessing a struct created in C in javascript, given that the pointer to the struct is passed into javascript as an external library.
Take a look at the following code:
C:
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
struct test_st;
extern void read_struct(struct test_st *mys, int siz);
struct test_st{
uint32_t my_number;
uint8_t my_char_array[32];
};
int main(){
struct test_st *teststr = malloc(sizeof(struct test_st));
teststr->my_number = 500;
for(int i = 0; i < 32; i++){
teststr->my_char_array[i] = 120 + i;
}
for(int i = 0; i < 32; i++){
printf("%d\n",teststr->my_char_array[i]);
}
read_struct(teststr,sizeof(teststr));
return 0;
}
Javascript:
mergeInto(LibraryManager.library,
{
read_struct: function(mys,siz){
var read_ptr = 0;
console.log("my_number: " + getValue(mys + read_ptr, 'i32'));
read_ptr += 4;
for(var i = 0; i < 32; i++){
console.log("my_char[" + i + "]: " + getValue(mys + read_ptr, 'i8'));
read_ptr += 1;
};
},
});
This is then compiled using emcc cfile.c --js-library jsfile.js.
The issue here is that you can't really read structs in javascript, you have to get memory from the respective addresses according to the size of the struct field (so read 4 bytes from the uint32_t and 1 byte from the uint8_t). Ok, that wouldn't be an issue, except you also have to state the LLVM IR type for getValue to work, and it doesn't include unsigned types, so in the case of the array, it will get to 127 and overflow to -128, when the intended behaviour is to keep going up, since the variable is unsigned.
I looked everywhere for an answer but apparently this specific intended behaviour is not common. Changing the struct wouldn't be possible in the program I'm applying this to (not the sample one above).
One way is to use the HEAP* typed arrays exposed by Emscripten, which do have unsigned views:
mergeInto(LibraryManager.library, {
read_struct: function(myStructPointer, size) {
// Assumes the struct starts on a 4-byte boundary
var myNumber = HEAPU32[myStructPointer/4];
console.log(myNumber);
// Assumes my_char_array is immediately after my_number with no padding
var myCharArray = HEAPU8.subarray(myStructPointer+4, myStructPointer+4+32);
console.log(myCharArray);
}
});
This works in my test, running Emscripten 1.29.0-64bit, but as noted it makes assumptions about alignment/padding. The cases I tested seemed to show that a struct seemed to always start on a 4 byte boundary, and that 32 bit unsigned integers inside a struct were also always aligned on a 4 byte boundary, and so accessible by HEAPU32.
However, it's beyond my knowledge to know if you can depend on this behaviour in Emscripten. It's my understanding that you can't in usual C/C++ world.