Add native extensions for the Dart shell to the Windows platform and the Mac OS X platform.

BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com//9465004

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@5235 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
whesse@google.com 2012-03-09 14:34:57 +00:00
parent 4f1ac7c8c6
commit 3c6d3843fc
10 changed files with 166 additions and 88 deletions

View file

@ -346,7 +346,15 @@
'link_settings': {
'libraries': [ '-lws2_32.lib', '-lRpcrt4.lib' ],
},
}]],
# Generate an import library on Windows, by exporting a function.
# Extensions use this import library to link to the API in dart.exe.
'msvs_settings': {
'VCLinkerTool': {
'AdditionalOptions': [ '/EXPORT:Dart_True' ],
},
},
}],
],
},
{
# dart binary without any snapshot built in.
@ -421,27 +429,38 @@
}],
],
},
],
'conditions': [
['OS=="linux"', {
'targets': [
{
'target_name': 'test_extension',
'type': 'shared_library',
'dependencies': [
],
'include_dirs': [
'.',
],
'sources': [
'test_extension_linux.cc',
],
'defines': [
'DART_SHARED_LIB',
],
},
{
'target_name': 'test_extension',
'type': 'shared_library',
'dependencies': [
'dart',
],
}],
'include_dirs': [
'..',
],
'sources': [
'test_extension.cc',
'test_extension_dllmain_win.cc',
],
'defines': [
'DART_SHARED_LIB',
],
'conditions': [
['OS=="win"', {
'msvs_settings': {
'VCLinkerTool': {
'AdditionalDependencies': [ 'dart.lib' ],
'AdditionalLibraryDirectories': [ '<(PRODUCT_DIR)' ],
},
},
}],
['OS=="mac"', {
'xcode_settings': {
'OTHER_LDFLAGS': [ '-undefined', 'dynamic_lookup' ],
},
}],
],
},
],
}

View file

@ -21,6 +21,7 @@
'eventhandler_win.cc',
'eventhandler_win.h',
'extensions.h',
'extensions.cc',
'extensions_linux.cc',
'extensions_macos.cc',
'extensions_win.cc',

57
runtime/bin/extensions.cc Normal file
View file

@ -0,0 +1,57 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "bin/extensions.h"
#include <stdio.h>
#include "include/dart_api.h"
#include "platform/assert.h"
#include "platform/globals.h"
#include "bin/dartutils.h"
Dart_Handle Extensions::LoadExtension(const char* extension_url,
Dart_Handle parent_library) {
ASSERT(DartUtils::IsDartExtensionSchemeURL(extension_url));
const char* library_name =
extension_url + strlen(DartUtils::kDartExtensionScheme);
if (strchr(library_name, '/') != NULL ||
strchr(library_name, '\\') != NULL) {
return Dart_Error("path components not allowed in extension library name");
}
void* library_handle = LoadExtensionLibrary(library_name);
if (!library_handle) {
return Dart_Error("cannot find extension library");
}
const char* strings[3] = { library_name, "_Init", NULL };
char* init_function_name = Concatenate(strings);
typedef Dart_Handle (*InitFunctionType)(Dart_Handle import_map);
InitFunctionType fn = reinterpret_cast<InitFunctionType>(
ResolveSymbol(library_handle, init_function_name));
free(init_function_name);
if (fn == NULL) {
return Dart_Error("cannot find initialization function in extension");
}
return (*fn)(parent_library);
}
// Concatenates a NULL terminated array of strings.
// The returned string must be freed.
char* Extensions::Concatenate(const char** strings) {
int size = 1; // null termination.
for (int i = 0; strings[i] != NULL; i++) {
size += strlen(strings[i]);
}
char* result = reinterpret_cast<char*>(malloc(size));
int index = 0;
for (int i = 0; strings[i] != NULL; i++) {
index += snprintf(result + index, size - index, "%s", strings[i]);
}
ASSERT(index == size - 1);
ASSERT(result[size - 1] == '\0');
return result;
}

View file

@ -10,13 +10,19 @@
class Extensions {
public:
// TODO(whesse): Make loading extensions lazy, so dynamic library is loaded
// only when first native function is called.
// TODO(whesse): Make extension load from a relative path relative to
// the library it is in. Currently loads from current working directory.
static Dart_Handle LoadExtension(const char* extension_url,
Dart_Handle library);
Dart_Handle parent_library);
private:
// The returned string must be freed.
static char* Concatenate(const char** strings);
// Platform-specific implementations.
static void* LoadExtensionLibrary(const char* library_name);
static void* ResolveSymbol(void* lib_handle, const char* symbol);
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(Extensions);
};

View file

@ -2,44 +2,19 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include <stdio.h>
#include "bin/extensions.h"
#include <dlfcn.h>
#include "include/dart_api.h"
#include "platform/assert.h"
#include "platform/globals.h"
#include "bin/extensions.h"
#include "bin/dartutils.h"
Dart_Handle Extensions::LoadExtension(const char* extension_url,
Dart_Handle parent_library) {
// TODO(whesse): Consider making loading extensions lazy, so the
// dynamic library is loaded only when first native function is called.
ASSERT(DartUtils::IsDartExtensionSchemeURL(extension_url));
const char* library_name =
extension_url + strlen(DartUtils::kDartExtensionScheme);
if (strchr(library_name, '/') != NULL) {
return Dart_Error("path components not allowed in extension library name");
}
const int buffer_length = strlen(library_name) + strlen("./lib.so") + 1;
char* library_path = new char[buffer_length];
snprintf(library_path, buffer_length, "./lib%s.so", library_name);
void* Extensions::LoadExtensionLibrary(const char* library_name) {
const char* strings[4] = { "./lib", library_name, ".so", NULL };
char* library_path = Concatenate(strings);
void* lib_handle = dlopen(library_path, RTLD_LAZY);
if (!lib_handle) {
delete[] library_path;
return Dart_Error("cannot find extension library");
}
// Reuse library_path buffer for intialization function name.
char* library_init_function = library_path;
snprintf(library_init_function, buffer_length, "%s_Init", library_name);
typedef Dart_Handle (*InitFunctionType)(Dart_Handle import_map);
InitFunctionType fn = reinterpret_cast<InitFunctionType>(
dlsym(lib_handle, library_init_function));
delete[] library_path;
char *error = dlerror();
if (error != NULL) {
return Dart_Error(error);
}
return (*fn)(parent_library);
free(library_path);
return lib_handle;
}
void* Extensions::ResolveSymbol(void* lib_handle, const char* symbol) {
void* result = dlsym(lib_handle, symbol);
if (dlerror() != NULL) return NULL;
return result;
}

View file

@ -3,12 +3,18 @@
// BSD-style license that can be found in the LICENSE file.
#include "bin/extensions.h"
#include <dlfcn.h>
#include "include/dart_api.h"
#include "platform/assert.h"
Dart_Handle Extensions::LoadExtension(const char* extension_url,
Dart_Handle parent_library) {
UNIMPLEMENTED();
return NULL;
void* Extensions::LoadExtensionLibrary(const char* library_name) {
const char* strings[4] = { "./lib", library_name, ".dylib", NULL };
char* library_path = Concatenate(strings);
void* lib_handle = dlopen(library_path, RTLD_LAZY);
free(library_path);
return lib_handle;
}
void* Extensions::ResolveSymbol(void* lib_handle, const char* symbol) {
void* result = dlsym(lib_handle, symbol);
if (dlerror() != NULL) return NULL;
return result;
}

View file

@ -4,11 +4,14 @@
#include "bin/extensions.h"
#include "include/dart_api.h"
#include "platform/assert.h"
Dart_Handle Extensions::LoadExtension(const char* extension_url,
Dart_Handle parent_library) {
UNIMPLEMENTED();
return NULL;
void* Extensions::LoadExtensionLibrary(const char* library_name) {
const char* strings[3] = { library_name, ".dll", NULL };
char* library_path = Concatenate(strings);
void* lib_handle = LoadLibrary(library_path);
free(library_path);
return lib_handle;
}
void* Extensions::ResolveSymbol(void* lib_handle, const char* symbol) {
return GetProcAddress(reinterpret_cast<HMODULE>(lib_handle), symbol);
}

View file

@ -1,23 +1,22 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include <string.h>
#include "../include/dart_api.h"
#include "include/dart_api.h"
#define EXPORT_SYMBOL __attribute__ ((visibility ("default")))
Dart_NativeFunction ResolveName(Dart_Handle name, int argc);
extern "C" Dart_NativeFunction ResolveName(Dart_Handle name, int argc);
DART_EXPORT Dart_Handle test_extension_Init(Dart_Handle parent_library) {
if (Dart_IsError(parent_library)) { return parent_library; }
extern "C" EXPORT_SYMBOL Dart_Handle test_extension_Init(Dart_Handle library) {
if (Dart_IsError(library)) return library;
Dart_Handle check_return = Dart_SetNativeResolver(library, ResolveName);
if (Dart_IsError(check_return)) return check_return;
return Dart_Null();
Dart_Handle result_code = Dart_SetNativeResolver(parent_library, ResolveName);
if (Dart_IsError(result_code)) return result_code;
return parent_library;
}
extern "C" void IfNull(Dart_NativeArguments arguments) {
void IfNull(Dart_NativeArguments arguments) {
Dart_Handle object = Dart_GetNativeArgument(arguments, 0);
if (Dart_IsNull(object)) {
Dart_SetReturnValue(arguments, Dart_GetNativeArgument(arguments, 1));
@ -26,7 +25,7 @@ extern "C" void IfNull(Dart_NativeArguments arguments) {
}
}
extern "C" Dart_NativeFunction ResolveName(Dart_Handle name, int argc) {
Dart_NativeFunction ResolveName(Dart_Handle name, int argc) {
assert(Dart_IsString8(name));
const char* cname;
Dart_Handle check_error;
@ -35,7 +34,7 @@ extern "C" Dart_NativeFunction ResolveName(Dart_Handle name, int argc) {
if (Dart_IsError(check_error)) {
Dart_PropagateError(check_error);
}
if (!strcmp("Cat_IfNull", cname) && argc == 2) {
if (!strcmp("TestExtension_IfNull", cname) && argc == 2) {
return IfNull;
}
return NULL;

View file

@ -0,0 +1,12 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
BOOL APIENTRY DllMain(HMODULE module,
DWORD reason,
LPVOID reserved) {
return true;
}

View file

@ -14,5 +14,5 @@ class Cat {
String toString() => 'cat $x';
// Implements (a != null) ? a : b using a native C++ function and the API.
static int ifNull(a, b) native 'Cat_IfNull';
static int ifNull(a, b) native 'TestExtension_IfNull';
}