Native extensions - C ++ native libraries

Extension_samples work fine with the C library, but what about C ++ libraries?

I have a class-based C ++ library that I want to use as a native extension, so we have, for example: -

class Connect {
      open(...);
  ....
}

in C ++, and I need a similar class in Dart.

Looking at dart_api.h and dart_native_api.h, it is not clear to me how I pass class pointers back and forth from C ++ to Dart and how I call methods on them and bind this to an instance of the Dart class. How does ResolveName work with connect-> open () calls, or do we do it in a completely different way.

+4
source share
2 answers

Okay, dig a little, and I was discussing it now, I am doing it in Dart: -

bool open() native 'Connection::open';

"Connection:: open", native. , , "connectionOpen" "messageOpen" .., .

+2

, :

cpp_extension.cc

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#ifdef _WIN32
#include "windows.h"
#else
#include <stdbool.h>
#include <dlfcn.h>
#include <unistd.h>
#include <sys/mman.h>
#endif

#include "dart_api.h"

Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool* auto_setup_scope);

DART_EXPORT Dart_Handle cpp_extension_Init(Dart_Handle parent_library) {
  if (Dart_IsError(parent_library)) { return parent_library; }

  Dart_Handle result_code = Dart_SetNativeResolver(parent_library, ResolveName);
  if (Dart_IsError(result_code)) return result_code;

  return Dart_Null();
}

Dart_Handle HandleError(Dart_Handle handle) {
  if (Dart_IsError(handle)) Dart_PropagateError(handle);
  return handle;
}

class Connection {
  int* buffer;
  bool opened;

  public:
    Connection() {
      opened = false;
      buffer = new int[1000000];
      memset(buffer, 1, 1000000);
    }

    void close() {
      opened = false;
    } 

    void open(const char* connectionString) {
      opened = true;
    }

    ~Connection() {
      delete buffer;
    }
};

void ConnectionClose(Dart_NativeArguments arguments) {
  Connection* connection;
  Dart_Handle dh_handle;

  Dart_EnterScope();
  dh_handle = Dart_GetNativeArgument(arguments, 0);
  connection = (Connection*)dh_handle;
  connection->close();
  Dart_Handle result = Dart_Null();
  Dart_SetReturnValue(arguments, result);
  Dart_ExitScope();
}

void ConnectionCreate(Dart_NativeArguments arguments) {  
  Connection* connection;
  Dart_Handle result;

  Dart_EnterScope();
  connection = new Connection();
  result = Dart_NewInteger((int64_t)connection);
  Dart_SetReturnValue(arguments, result);
  Dart_ExitScope();
}

void ConnectionPeerFinalizer(Dart_WeakPersistentHandle handle, void *peer) {
  delete (Connection*) peer;
}

void ConnectionPeerRegister(Dart_NativeArguments arguments) {
  int64_t peer;
  Dart_Handle dh_object;
  Dart_Handle dh_peer;

  Dart_EnterScope();
  dh_object = Dart_GetNativeArgument(arguments, 0);
  dh_peer = Dart_GetNativeArgument(arguments, 1);
  Dart_IntegerToInt64(dh_peer, &peer);
  Dart_NewWeakPersistentHandle(dh_object, (void*)peer, ConnectionPeerFinalizer);
  Dart_SetReturnValue(arguments, Dart_Null());
  Dart_ExitScope();
}

void ConnectionOpen(Dart_NativeArguments arguments) { 
  Connection* connection;
  const char* connectionString;
  Dart_Handle dh_connectionString;
  Dart_Handle dh_handle;

  Dart_EnterScope();
  dh_handle = Dart_GetNativeArgument(arguments, 0);
  dh_connectionString = Dart_GetNativeArgument(arguments, 1);
  Dart_StringToCString(dh_connectionString, &connectionString);
  connection = (Connection*)dh_handle;
  connection->open(connectionString);  
  Dart_Handle result = Dart_Null();
  Dart_SetReturnValue(arguments, result);
  Dart_ExitScope();
}

struct FunctionLookup {
  const char* name;
  Dart_NativeFunction function;
};

FunctionLookup function_list[] = {
  {"ConnectionClose", ConnectionClose},
  {"ConnectionCreate", ConnectionCreate},
  {"ConnectionOpen", ConnectionOpen},
  {"ConnectionPeerRegister", ConnectionPeerRegister},
  {NULL, NULL}};

Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool* auto_setup_scope) {
  if (!Dart_IsString(name)) return NULL;
  Dart_NativeFunction result = NULL;
  Dart_EnterScope();
  const char* cname;
  HandleError(Dart_StringToCString(name, &cname));

  for (int i=0; function_list[i].name != NULL; ++i) {
    if (strcmp(function_list[i].name, cname) == 0) {
      result = function_list[i].function;
      break;
    }
  }
  Dart_ExitScope();
  return result;
}

cpp_extension.dart

library dart_and_cpp_classes.ext_cpp_extension;

import "dart-ext:cpp_extension";

class Connection {
  final String connectionString;

  int _handle;

  bool _opened = false;

  Connection(this.connectionString) {
    _handle = _create();
    _peerRegister(this, _handle);
  }

  bool get opened => _opened;

  void close() {
    _close(_handle);
    _opened = false;
  }

  void open() {
    _open(_handle, connectionString);
    _opened = true;
  }

  int _create() native "ConnectionCreate";

  void _close(int handle) native "ConnectionClose";

  void _open(int handle, String connectionString) native "ConnectionOpen";

  void _peerRegister(Object object, int handle) native "ConnectionPeerRegister";
}

use_cpp_extension.dart

import 'package:dart_and_cpp_classes/cpp_extension.dart';

void main() {
  var count = 500;
  var connections = [];
  for(var i = 0; i < count; i++) {
    var connection = new Connection("MYSQL");
    connection.open();
    connection.close();
    connections.add(connection);
  }

  connections = null;
  print("Done");
}

( ) github: https://github.com/mezoni/dart_and_cpp_classes

.

Run:

  • /build _cpp_extension.dart
  • /use _cpp_extension.dart

P.S.

++.

, .

+5

All Articles