Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

native extension Dart

I'm trying to build a native extension in dart for postgresql. I have compiled the CC file in .o then in .so (shared object i guess). It's now named libpsql.so and I placed it in the the same directory as my .dart file. The first line of dart file is #import(dart-ext:libpsql); but it keeps telling me that the resources is unavailable.

My dart code

#library("psql");

#import("dart-ext:libpsql_dart");

class Database {
  var mDb;
  var mUser;
  var mDbname;
  var mPasswd;
  var mHost;
  var mPort;
  var mTable;

  //String toString() => "<PostgreSQL: $user@$_host:$_port/$_table>";
  Database(host,user,passwd,dbname) : this.mUser = user, this.mHost = host, this.mPasswd = passwd, this.mDbname = dbname  {
    mDb = _connect(host,user,passwd,dbname);
  }

}
_connect(host,user,passwd,dbname) native 'Connect';

And here is my C++ code.

#include <string.h>
#include <stdio.h>
#include <libpq-fe.h>
#include "dart_api.h"

Dart_NativeFunction ResolveName(Dart_Handle name, int argc);

DART_EXPORT Dart_Handle psql_dart_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;
}
void Connect(Dart_NativeArguments args) {
    Dart_EnterScope();
    PGconn *conn;
    const char *conninfo = "user=postgres;password=postgres;host=localhost;port=5432;dbname=reviewdb";
    conn = PQconnectdb(conninfo);

    /* Check to see that the backend connection was successfully made */
    if (PQstatus(conn) != CONNECTION_OK)
    {
        fprintf(stderr, "Connection to database failed: %s",
                PQerrorMessage(conn));
        PQfinish(conn);
    }

  Dart_Handle result = HandleError(Dart_NewInteger((int64_t) conn));
  Dart_SetReturnValue(args, result);

  Dart_ExitScope();
}

Dart_NativeFunction ResolveName(Dart_Handle name, int argc) {
  assert(Dart_IsString8(name));
  const char* cname;
  Dart_Handle check_error = Dart_StringToCString(name, &cname);
  if (Dart_IsError(check_error)) Dart_PropagateError(check_error);
  Dart_NativeFunction result = NULL;
  if (strcmp("Connect", cname) == 0) result = Connect;
  Dart_ExitScope();
  return result;
}

Html script include

<script type="application/dart" src="web/lib/psql.dart"></script> 
    <script type="application/dart" src="web/test_dart.dart"></script>

And the last, my compile command line :

g++ -fPIC --verbose -I/home/{linux user}/Documents/dart/dart-sdk/include/ -lpq -I/usr/include/postgresql -c psql_dart.cc

gcc -shared -Wl,-soname,libpsql.so -o libpsql.so psql_dart.o

After testing new code i commented my function Connect like this :

void Connect(Dart_NativeArguments args) {
    Dart_EnterScope();
//    PGconn *conn;
//    const char *conninfo = "user=postgres password=postgres host=localhost port=5432";
//    conn = PQconnectdb(conninfo);
//
//    /* Check to see that the backend connection was successfully made */
//    if (PQstatus(conn) != CONNECTION_OK)
//    {
//        fprintf(stderr, "Connection to database failed: %s",
//                PQerrorMessage(conn));
//        PQfinish(conn);
//        exit(1);
//    }
//  PQfinish(conn);

  Dart_Handle result = HandleError(Dart_NewInteger( 0));
  Dart_SetReturnValue(args, result);

  Dart_ExitScope();
}

The output :

worked?
Segmentation fault (core dumped)

And I still get the SegFault any idea?

My gdb stacktrace :

Starting program: /home/<user>/Documents/dart/dart-sdk/bin/dart test_dart.dart
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
worked?

Program received signal SIGSEGV, Segmentation fault.
dart::Api::NewHandle (isolate=0x948a40, raw=0x7ffff7f80021) at runtime/vm/dart_api_impl.cc:114
114 runtime/vm/dart_api_impl.cc: No such file or directory.
(gdb) bt
#0  dart::Api::NewHandle (isolate=0x948a40, raw=0x7ffff7f80021) at runtime/vm/dart_api_impl.cc:114
#1  0x000000000042e121 in dart::Dart_Invoke (target=<optimized out>, name=0x959b90, number_of_arguments=<optimized out>, arguments=<optimized out>) at runtime/vm/dart_api_impl.cc:3543
#2  0x00000000004097ee in main (argc=<optimized out>, argv=<optimized out>) at runtime/bin/main.cc:724
like image 542
poudigne Avatar asked Oct 02 '12 12:10

poudigne


Video Answer


1 Answers

After playing around some with your code and getting the postgresql-dev-9.1 package installed this is where I am. Currently it still does not run, however it is due to a linking error not due to the import itself.

Note a change to your C++ file: I renamed your initialization function from: psql_dart_Init to just psql_Init

// libpsql.cc
#include <string.h>
#include <stdio.h>
#include <libpq-fe.h>
#include "dart_api.h"

Dart_NativeFunction ResolveName(Dart_Handle name, int argc);

DART_EXPORT Dart_Handle psql_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;
}

void Connect(Dart_NativeArguments args) {
    Dart_EnterScope();
    PGconn *conn;
    const char *conninfo = "user=postgres;password=postgres;host=localhost;port=5432;dbname=reviewdb";
    conn = PQconnectdb(conninfo);

    /* Check to see that the backend connection was successfully made */
    if (PQstatus(conn) != CONNECTION_OK)
    {
        fprintf(stderr, "Connection to database failed: %s",
                PQerrorMessage(conn));
        PQfinish(conn);
    }

  Dart_Handle result = HandleError(Dart_NewInteger((int64_t) conn));
  Dart_SetReturnValue(args, result);

  Dart_ExitScope();
}

Dart_NativeFunction ResolveName(Dart_Handle name, int argc) {
  assert(Dart_IsString8(name));
  const char* cname;
  Dart_Handle check_error = Dart_StringToCString(name, &cname);
  if (Dart_IsError(check_error)) Dart_PropagateError(check_error);
  Dart_NativeFunction result = NULL;
  if (strcmp("Connect", cname) == 0) result = Connect;
  Dart_ExitScope();
  return result;
}

And the following is my 1st dart file:

// psql.dart
#library("psql");

#import("dart-ext:psql");

class Database {
  var mDb;
  var mUser;
  var mDbname;
  var mPasswd;
  var mHost;
  var mPort;
  var mTable;

  //String toString() => "<PostgreSQL: $user@$_host:$_port/$_table>";
  Database(host,user,passwd,dbname) : this.mUser = user, this.mHost = host, this.mPasswd = passwd, this.mDbname = dbname  {
    mDb = _connect(host,user,passwd,dbname);
  }

}
_connect(host,user,passwd,dbname) native 'Connect';

And then the actual VERY minimal application (command line instead of dartium-based) to test it.

// test.dart
#import('psql.dart');

main() {
  var database = new Database('localhost', 'mbutler', 'test', 'test');

  if(database != null) {
    print('worked?');
  }
}

I used the following command to compile and link in one go and I it does work correctly. I segfault because I don't have a valid database to connect to but the following does load the native library properly:

g++ -O2 -DDART_SHARED_LIB -I/home/<user>/dart/dart-sdk/include -rdynamic -fPIC -shared libpsql.cc -lpq -I/usr/include/postgresql -o libpsql.so

(Thanks to dart-sqlite build script was able to piece together the linking I required)

like image 92
Matt B Avatar answered Oct 01 '22 01:10

Matt B