Skip to content

Commit 9e74ab4

Browse files
author
Mihail Slavchev
committed
Merge pull request #285 from NativeScript/slavchev/require-native-modules
add support for native modules
2 parents 485600f + 6f3cd44 commit 9e74ab4

File tree

7 files changed

+75
-6
lines changed

7 files changed

+75
-6
lines changed

src/jni/Module.cpp

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <sstream>
1818
#include <assert.h>
1919
#include <libgen.h>
20+
#include <dlfcn.h>
2021

2122
using namespace v8;
2223
using namespace std;
@@ -170,13 +171,20 @@ void Module::RequireCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
170171
}
171172
}
172173

174+
void Module::RequireNativeCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
175+
{
176+
auto ext = args.Data().As<External>();
177+
auto funcPtr = reinterpret_cast<FunctionCallback>(ext->Value());
178+
funcPtr(args);
179+
}
180+
173181
Local<Object> Module::Load(const string& path, bool& isData)
174182
{
175183
Local<Object> result;
176184

177185
auto isolate = Isolate::GetCurrent();
178186

179-
if (Util::EndsWith(path, ".js"))
187+
if (Util::EndsWith(path, ".js") || Util::EndsWith(path, ".so"))
180188
{
181189
isData = false;
182190
result = LoadModule(isolate, path);
@@ -213,12 +221,44 @@ Local<Object> Module::LoadModule(Isolate *isolate, const string& modulePath)
213221

214222
Local<Function> moduleFunc;
215223

216-
auto script = LoadScript(isolate, modulePath, fullRequiredModulePath);
224+
if (Util::EndsWith(modulePath, ".js"))
225+
{
226+
auto script = LoadScript(isolate, modulePath, fullRequiredModulePath);
217227

218-
moduleFunc = script->Run().As<Function>();
219-
if (tc.HasCaught())
228+
moduleFunc = script->Run().As<Function>();
229+
if (tc.HasCaught())
230+
{
231+
throw NativeScriptException(tc, "Error running script " + modulePath);
232+
}
233+
}
234+
else if (Util::EndsWith(modulePath, ".so"))
220235
{
221-
throw NativeScriptException(tc, "Error running script " + modulePath);
236+
auto handle = dlopen (modulePath.c_str(), RTLD_LAZY);
237+
if (handle == nullptr)
238+
{
239+
auto error = dlerror();
240+
string errMsg(error);
241+
throw NativeScriptException(errMsg);
242+
}
243+
auto func = dlsym(handle, "NSMain");
244+
if (func == nullptr)
245+
{
246+
string errMsg("Cannot find 'NSMain' in " + modulePath);
247+
throw NativeScriptException(errMsg);
248+
}
249+
auto extFunc = External::New(isolate, func);
250+
auto ft = FunctionTemplate::New(isolate, RequireNativeCallback, extFunc);
251+
auto maybeFunc = ft->GetFunction(isolate->GetCurrentContext());
252+
if (maybeFunc.IsEmpty() || tc.HasCaught())
253+
{
254+
throw NativeScriptException(tc, "Cannot create native module function callback");
255+
}
256+
moduleFunc = maybeFunc.ToLocalChecked();
257+
}
258+
else
259+
{
260+
string errMsg = "Unsupported file extension: " + modulePath;
261+
throw NativeScriptException(errMsg);
222262
}
223263

224264
auto fileName = ConvertToV8String(modulePath);

src/jni/Module.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ namespace tns
3636

3737
static void RequireCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
3838

39+
static void RequireNativeCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
40+
3941
static v8::Local<v8::Function> GetRequireFunction(v8::Isolate *isolate, const std::string& dirName);
4042

4143
static v8::ScriptCompiler::CachedData* TryLoadScriptCache(const std::string& path);

src/src/com/tns/Module.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,10 @@ private static File getFileWithExtension(String path)
203203
String fallbackExtension;
204204

205205
boolean isJSFile = path.endsWith(".js");
206+
boolean isSOFile = path.endsWith(".so");
206207
boolean isJSONFile = path.endsWith(".json");
207208

208-
if (isJSFile || isJSONFile)
209+
if (isJSFile || isJSONFile || isSOFile)
209210
{
210211
fallbackExtension = "";
211212
}

test-app/assets/app/mainpage.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ require("./tests/extendedClassesTests");
2222
require("./tests/extendClassNameTests");
2323
require("./tests/testJniReferenceLeak");
2424
require("./tests/testRequireJSON");
25+
require("./tests/testNativeModules");
2526
require("./tests/requireExceptionTests");
2627

2728
var MainActivity = {
17.1 KB
Binary file not shown.
9.04 KB
Binary file not shown.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
describe("Tests native modules)", function () {
2+
3+
it("should load native module", function () {
4+
var x = 12;
5+
var y = 34;
6+
7+
var arch;
8+
var sysArch = java.lang.System.getProperty("os.arch");
9+
var lcArch = sysArch.toLowerCase();
10+
if (lcArch.indexOf("arm") > -1) {
11+
arch = "arm";
12+
} else if (lcArch.indexOf("i686") > -1) {
13+
arch = "x86";
14+
} else {
15+
throw new Error("Unsupported architecture=" + sysArch);
16+
}
17+
18+
var calc = require("../modules/libCalc-" + arch + ".so");
19+
20+
var sum = calc.add(x, y);
21+
22+
expect(sum).toBe(46);
23+
});
24+
25+
});

0 commit comments

Comments
 (0)