我在C ++项目中使用JavascriptCore,我不知道如何将C ++类暴露给javascript。例如,在Objective-C中是这样的:
@protocol MyPointExports <JSExport>
@property double x;
@property double y;
- (NSString *)description;
- (instancetype)initWithX:(double)x y:(double)y;
+ (MyPoint *)makePointWithX:(double)x y:(double)y;
@end
@interface MyPoint : NSObject <MyPointExports>
- (void)myPrivateMethod; // Not in the MyPointExports protocol, so not visible to JavaScript code.
@end
@implementation MyPoint
// ...
@end
JSContext *context = [[JSContext alloc] init];
// export MyPoint class
context[@"MyPoint"] = [MyPoint class];
但我不知道如何将JSExport和协议转换为C ++。
答案 0 :(得分:1)
看起来您需要使用C API来实现这一目标。有关详细信息,请参阅this article。特别是,&#34;将本地对象定义为JavaScript&#34;部分。
引用文章的列表与您想要实现的内容非常相似:
#include <iostream>
#include <JavaScriptCore/JavaScriptCore.h>
#include <sys/stat.h>
using namespace std;
struct FilesystemPrivate {
string path;
bool is_directory;
bool is_file;
bool is_symlink;
size_t size;
bool exists;
};
std::string JSStringToStdString(JSStringRef jsString) {
size_t maxBufferSize = JSStringGetMaximumUTF8CStringSize(jsString);
char* utf8Buffer = new char[maxBufferSize];
size_t bytesWritten = JSStringGetUTF8CString(jsString, utf8Buffer, maxBufferSize);
std::string utf_string = std::string (utf8Buffer, bytesWritten -1); // the last byte is a null \0 which std::string doesn't need.
delete [] utf8Buffer;
return utf_string;
}
JSValueRef ObjectCallAsFunctionCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
for (size_t i=0; i<argumentCount; i++) {
JSStringRef pathString = JSValueToStringCopy(ctx, arguments[i], nullptr);
cout << JSStringToStdString(pathString);
}
cout << endl ;
return JSValueMakeUndefined(ctx);
}
void setAttributes(FilesystemPrivate *fs, std::string path) {
fs->path = path;
struct stat statbuf;
if (lstat(path.c_str(), &statbuf) != -1) {
switch (statbuf.st_mode & S_IFMT){
case S_IFREG:
fs->is_file = true;
break;
case S_IFLNK:
fs->is_symlink = true;
break;
case S_IFDIR:
fs->is_directory = true;
break;
}
fs->size = statbuf.st_size;
fs->exists = true;
}else{
fs->exists = false;
fs->is_file = false;
fs->is_directory = false;
fs->is_symlink = false;
fs->size = 0;
}
}
/* callbacks */
void Filesystem_Finalize(JSObjectRef object){
FilesystemPrivate *fs = static_cast<FilesystemPrivate*>(JSObjectGetPrivate(object));
delete fs;
}
JSObjectRef Filesystem_CallAsConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
FilesystemPrivate *fs = new FilesystemPrivate();
JSStringRef pathString = JSValueToStringCopy(ctx, arguments[0], nullptr);
setAttributes(fs, JSStringToStdString(pathString));
JSObjectSetPrivate(constructor, static_cast<void*>(fs));
return constructor;
}
/* static values */
JSValueRef Filesystem_getPath(JSContextRef ctx, JSObjectRef object,JSStringRef propertyName, JSValueRef* exception) {
FilesystemPrivate *fs = static_cast<FilesystemPrivate*>(JSObjectGetPrivate(object));
JSStringRef pathString = JSStringCreateWithUTF8CString(fs->path.c_str());
return JSValueMakeString(ctx, pathString);
}
bool Filesystem_setPath(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) {
FilesystemPrivate *fs = static_cast<FilesystemPrivate*>(JSObjectGetPrivate(object));
JSStringRef pathString = JSValueToStringCopy(ctx, value, nullptr);
setAttributes(fs, JSStringToStdString(pathString));
return true;
}
JSValueRef Filesystem_getType(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) {
FilesystemPrivate *fs = static_cast<FilesystemPrivate*>(JSObjectGetPrivate(object));
JSStringRef pathType;
if (fs->is_file) {
pathType = JSStringCreateWithUTF8CString("File");
}else if (fs->is_directory) {
pathType = JSStringCreateWithUTF8CString("Directory");
}else if (fs->is_symlink) {
pathType = JSStringCreateWithUTF8CString("Symlink");
}else{
pathType = JSStringCreateWithUTF8CString("Unknown");
}
return JSValueMakeString(ctx, pathType);
}
JSValueRef Filesystem_getExist(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) {
FilesystemPrivate *fs = static_cast<FilesystemPrivate*>(JSObjectGetPrivate(object));
return JSValueMakeBoolean(ctx, fs->exists);
}
JSValueRef Filesystem_getSize(JSContextRef ctx, JSObjectRef object,JSStringRef propertyName, JSValueRef* exception) {
FilesystemPrivate *fs = static_cast<FilesystemPrivate*>(JSObjectGetPrivate(object));
return JSValueMakeNumber(ctx, static_cast<double>(fs->size));
}
JSValueRef Filesystem_remove(JSContextRef ctx, JSObjectRef function, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
FilesystemPrivate *fs = static_cast<FilesystemPrivate*>(JSObjectGetPrivate(object));
remove(fs->path.c_str());
return JSValueMakeUndefined(ctx);
}
JSClassRef FilesystemClass() {
static JSClassRef filesystem_class;
if (!filesystem_class) {
JSClassDefinition classDefinition = kJSClassDefinitionEmpty;
static JSStaticFunction staticFunctions[] = {
{ "remove", Filesystem_remove, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ 0, 0, 0 }
};
static JSStaticValue staticValues[] = {
{ "path", Filesystem_getPath, Filesystem_setPath, kJSPropertyAttributeDontDelete },
{ "type", Filesystem_getType, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "exists", Filesystem_getExist, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "size", Filesystem_getSize, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ 0, 0, 0, 0 }
};
classDefinition.className = "Filesystem";
classDefinition.attributes = kJSClassAttributeNone;
classDefinition.staticFunctions = staticFunctions;
classDefinition.staticValues = staticValues;
classDefinition.finalize = Filesystem_Finalize;
classDefinition.callAsConstructor = Filesystem_CallAsConstructor;
filesystem_class = JSClassCreate(&classDefinition);
}
return filesystem_class;
}
int main(int argc, const char * argv[]) {
JSContextGroupRef contextGroup = JSContextGroupCreate();
JSGlobalContextRef globalContext = JSGlobalContextCreateInGroup(contextGroup, nullptr);
JSObjectRef globalObject = JSContextGetGlobalObject(globalContext);
JSObjectRef functionObject = JSObjectMakeFunctionWithCallback(globalContext, JSStringCreateWithUTF8CString("log"), ObjectCallAsFunctionCallback);
JSObjectSetProperty(globalContext, globalObject, JSStringCreateWithUTF8CString("log"), functionObject, kJSPropertyAttributeNone, nullptr);
JSObjectRef filesystemObject = JSObjectMake(globalContext, FilesystemClass(), nullptr);
JSObjectSetProperty(globalContext, globalObject, JSStringCreateWithUTF8CString("Filesystem"), filesystemObject, kJSPropertyAttributeNone, nullptr);
JSEvaluateScript(globalContext, JSStringCreateWithUTF8CString("var fs = new Filesystem('/Users/{user}/Desktop/file');log(fs.exists);"), nullptr, nullptr, 1, nullptr);
return 0;
}