Catalog
2. Modify HTML5ToolChain.cs file
3. Modify project_template.js file
3) EM_ASM_INT, EM_ASM_DOUBLE Has Return Value Method
1) In HTML5 JavaScriptFx. C++ function added in H extern "c"
2) In HTML5JavaScriptFx.js implementation of new functions in js
Example 1: Implement c++ call js to get a URL by modifying the source code
Example 2: Transferring data from c++ to js
2) New methods in HTML5 JavaScriptFx
1. js C++.
1.c++ Declaration:
//Declare c++ Functions //A declaration may or may not have a return value //Multiple functions can be declared in extern "c" //Parameters can be passed to functions extern "C" { #ifdef __EMSCRIPTEN__ EMSCRIPTEN_KEEPALIVE #endif char* web_get_data() { return (char*)BufferArray.GetData(); } void web_set_data(char* indata,int length) { if(length>sieof(Data)) { retrun; } Data = indata; } } //Note here that returning char* to js must return the uint8 array //BufferArray is defined as follows TArray<uint8> BufferArray; //FString to TArray<uint8>method: FString SendBuffer = "SendMessage"; FTCHARToUTF8 Converter(*SendBuff); BufferArray.SetNum(Converter.Length()); FMemory::Memcpy(BufferArray.GetData(), (uint8*)(ANSICHAR*)Converter.Get(), BufferArray.Num()); //This is the official way to view HTML5HTTP. SetContentAsString() in CPP
2. Modify HTML5ToolChain.cs file
In addition to declaring extern "c" functions, you also need to configure the precompiled file in the precompiled configuration, which is compiled in HTML5ToolChain.cs file, find the following two lines)
Result += " -s EXPORTED_FUNCTIONS=\"['_main', '_on_fatal']\""; Result += " -s EXTRA_EXPORTED_RUNTIME_METHODS=\"['Pointer_stringify', 'writeAsciiToMemory', 'stackTrace']\"";
Add the declared c++ function name to the first line, and note that you need to precede the function name with a horizontal bar'' (
Add a new call method'ccall'in the second line, modified as follows:
Result += " -s EXPORTED_FUNCTIONS=\"['_main', '_on_fatal','_web_get_data','_web_set_data']\""; Result += " -s EXTRA_EXPORTED_RUNTIME_METHODS=\"['Pointer_stringify', 'writeAsciiToMemory', 'stackTrace','ccall']\"";
3. Modify project_template.js file
//Find the declaration here at var UE4 var UE4 = { on_fatal: function() { try { UE4.on_fatal = Module.cwrap('on_fatal', null, ['string', 'string']); } catch(e) { UE4.on_fatal = function() {}; } }, web_get_data: function () { try { UE4.web_get_data = Module.ccall('web_get_data', null); } catch (e) { UE4.web_get_data = function () { }; } },web_set_data: function (indata,inlength) { try { UE4.web_set_data= Module.ccall('web_set_data', null,['string','string'],['number','number']); } catch (e) { UE4.web_set_data= function (indata,inlength) { }; } }, };
4. Call
When the above three steps are completed, c++ can be invoked through js
var data = Module.ccall('web_get_data','string'); Module.ccall('web_set_data',null,['string'],['number']) //Where Module. The values in the call indicate: //First parameter: function name //Second parameter: function return value type //Starting with the third parameter, is the type of parameter value of the function
2. Calling js by C++.
1. Inline
1) EM_JS Call:
//Declare EM_JS EM_JS(void,string_size,(),{ var str = "123456"; console.log(str.length); }); //Called in the cpp function string_size();
2)EM_ASM:
//Called directly in the cpp function EM_ASM({ console.log("print data"); }); //Can pass parameters int32 num = 10; EM_ASM({ console.log("Incoming number:"+$0); },num); //Multiple parameters can also be passed in int32 num1 = 10; bool bstring = true; EM_ASM({ console.log("Incoming number:"+$0 + $1); },num1,bstring); //Incoming parameter, expressed as $+ number in js
3) EM_ASM_INT, EM_ASM_DOUBLE Has Return Value Method
EM_ASM_INT({ return 1; }); EM_ASM_DOUBLE({ return 1.0; }); //Other return value methods are the same //Again, these calls are all passable
2.emscripten_run_script()
//This way, with EM_ASM is similar, but EM_ASM is more efficient emscripten_run_script("alert('c++ call!')");
3. Modify Source Code
1) In HTML5 JavaScriptFx. C++ function added in H extern "c"
2) In HTML5JavaScriptFx.js implementation of new functions in js
Note: Implementations in js need to be written in $UE_ In JSlib
Example 1: Implement c++ call js to get a URL by modifying the source code
In HTML5JavaScriptFx. Add void Get_to H URLData (const char* outdata, int outsize);
In HTML5JavaScriptFx.js implementation of new functions in js
//js implementation UE_GetURLString: function (outdata, outsize) { var hre = window.location.search; if (hre.length >= outsize) { console.log("window.location.href size harf then OutSize!!!") return; } hre = decodeURI(hre, "utf-8"); var newhre = window.btoa(encodeURIComponent(hre)); console.log(newhre); Module.writeAsciiToMemory(newhre, outdata); }, //It is important to note that Decode64 is used here. If you do not use transcoding, if you have Chinese or some symbols, you will encounter garbled or incomplete information when writing to c++ in memory.
Called in c++:
//By EM_ASM_INT Gets the length of the url int32 Hlength= EM_ASM_INT({ var hre = window.location.url; var newhre = window.btoa(encodeURIComponent(hre)); return newhre.length + 1; }); //Create char based on url length char OutData[Hlength]; //Call js implementation UE_GetURLString(OutData, sizeof(OutData)); //Transfer data to FString FString URL = FString(StringCast<TCHAR>(OutData).Get()); //Decode FString SaveURL; FBase64::Decode(URL,SaveULR); SaveURL = FGenericPlatformHttp::UrlDecode(SaveURL); //At this point, the URL was successfully retrieved from js
Example 2: Transferring data from c++ to js
1) EM_ASM implementation:
//Calling EM_in a function ASM //As mentioned above, EM_ASM can pass parameters, so pass them directly TArray<uint8> BufferArray; FString SendBuff = "Send Chinese Message"; //Decode64 is required to transcode SendBuff to prevent scrambling SendBuff = FGenericPlatformHttp::UrlEncode(SendBuff); SendBuff = FBase64::Encode(SendBuff ); //FString needs to be converted to TArray<uint8> FTCHARToUTF8 Converter(*SendBuff); BufferArray.SetNum(Converter.Length()); FMemory::Memcpy(BufferArray.GetData(), (uint8*)(ANSICHAR*)Converter.Get(), BufferArray.Num()); //Call EM_ASM EM_ASM({ //Convert uint8 array to make js recognizable var sdata = Module.HEAP8.subarray($0,$0+$1); //Convert uint8 array to string var dataString = ""; for (var i = 0; i < sdata.length; i++) { dataString += String.fromCharCode(sdata[i]); } //Decode var sendBuff = decodeURIComponent(window.atob(dataString)); //Print raw data console.log(sendBuff); //Set URL var URL = "http://............" //Send to server $.ajax({ url: URL, type: "post", data: { data: sendBuff }, dataType: 'text', async: true, success: function (res) { console.log("Send Message Success!"); // Successful callback function //alert('Successful Data Request') }, error: function (XMLHttpRequest, textStatus, errorThrown) { // Failed Callback Function console.log(XMLHttpRequest, textStatus, errorThrown); //alert('Failed to Request Data') } }); },(char*)BufferArray.GetData(),BufferArray.Num());
2) New methods in HTML5 JavaScriptFx
//In HTML5JavaScriptFx. Add in extern "c" of H void UE_PostRequest(const char* senddata,int sendlength); //In HTML5JavaScriptFx. New implementation in JS //Note that you want to write in $UE_ Inside JSlib UE_PostRequest:function(senddata,sendlength){ //Convert uint8 array var sdata = Module.HEAP8.subarray(senddata, senddata+ sendlength); //uint8 -> string var dataString = ""; for (var i = 0; i < sdata.length; i++) { dataString += String.fromCharCode(sdata[i]); } //Decode var sendBuff = decodeURIComponent(window.atob(dataString)); console.log(sendBuff); //Set URL var URL = "http://......."; $.ajax({ url: URL, type: "post", data: { data: sendBuff }, dataType: 'text', async: true, success: function (res) { console.log("Send Message Success!"); // Successful callback function //alert('Successful Data Request') }, error: function (XMLHttpRequest, textStatus, errorThrown) { // Failed Callback Function console.log(XMLHttpRequest, textStatus, errorThrown); //alert('Failed to Request Data') } }); }
Called in cpp
TArray<uint8> BufferArray; FString SendBuff = "Send Chinese Message"; //Decode64 is required to transcode SendBuff to prevent scrambling SendBuff = FGenericPlatformHttp::UrlEncode(SendBuff); SendBuff = FBase64::Encode(SendBuff ); //FString needs to be converted to TArray<uint8> FTCHARToUTF8 Converter(*SendBuff); BufferArray.SetNum(Converter.Length()); FMemory::Memcpy(BufferArray.GetData(), (uint8*)(ANSICHAR*)Converter.Get(), BufferArray.Num()); #ifdef __EMSCRIPTEN__ UE_PostRequest( (char*)BufferArray.GetData(), BufferArray.Num()); #endif //At this point, the js method call by c++ is complete
Note: The method that invokes js in cpp, either way, must contain the following header file
#ifdef __EMSCRIPTEN__ otherwise ignore". #include <emscripten/emscripten.h> #include <emscripten/html5.h> #else #define EMSCRIPTEN_KEEPALIVE #endif
And when writing, if you call a js method, you must do so, otherwise you will get an error when compiling your project unless you package HTML5 directly
#ifdef __EMSCRIPTEN__ //Calling the js implementation must write here #endif
These are the common methods of intermodulation between UE4 c++ and js, which can be found in the engine. I am here to make a collation and summary based on my own project and share it with you. I hope to help you, if there are any errors, I hope to correct them