Skip to content

An experiment in embedding Python in Dart via dart ffi and the Python c-api

Notifications You must be signed in to change notification settings

TimWhiting/dartpy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

57 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Usage

Dartpy is a library that allows dart to call out to python code by using the Python C-API embedding and dart:ffi. As such it is a fairly low level interface where you have to manage reference counts of python objects to help the python garbage collector.

However, there are a few high level functions that I've provided to automatically marshal the arguments to python and back and manage the reference counts for you.

Here are a few examples:

For a simple python script inline you can do the following: (Uses the low level C-API that is wrapped by dart:ffi).

void main(List<String> args) {
 dartpyc.Py_Initialize();
 final python = '''
 from time import time, ctime
 print("Today is", ctime(time()))
 ''';
 final pystring = python.toNativeUtf8();
 dartpyc.PyRun_SimpleString(pystring.cast<Int8>());
 malloc.free(pystring);
 print(dartpyc.Py_FinalizeEx());
}

For a more complex script that you don't want inline you can do this: (Uses a few higher level helper methods)

void main() {
  // initializes the python runtime
  pyStart();
  try {
    // imports a python module
    final pyModule = pyimport('multiply');
    // gets a function within that module
    final pFunc = pyModule.getFunction('multiply');
    // calls the function and gets the result
    final result = pFunc([1, 2]);
    print(result); // Should print 3
  } on DartPyException catch (e) {
    print(e);
    // Cleans up memory
    pyCleanup();
    exit(1);
  }
  // Cleans up memory
  pyCleanup();
  exit(0);
}

Feel free to contribute! This is a best effort project that I develop in my spare time.

Limitations

This library assumes that you have the python dynamic library in the following locations:

  • (MacOS) /usr/local/Frameworks/Python.framework/Versions/3.8/lib/libpython3.8.dylib
  • (Linux) /usr/lib/x86_64-linux-gnu/libpython3.8.so
  • (Windows)
          Map env = Platform.environment;
          String username =env["USERNAME"];
          
          pyLibLocation =
              'C:\\Users\\$username\\AppData\\Local\\Programs\\Python\\Python39\\python39.dll';
        
  • (android) wether can i use python from termux ,need to research;

To override this default location, put the following at the beginning of your script:

void main() {
  pyLibLocation = '/path/to/your/dynamic_library';
  // The rest of your code...
}

Eventually, maybe I will create a flutter package that bundles the dynamic library in the assets for each of the platforms, but currently I'm not doing that.

Not all objects are automatically marshalled back and forth, currently just supporting basic objects (int, double, String, num).

I'm working on an annotation and code generation library so that you can just annotate and call functions like so:

import 'package:dartpy/dartpy.dart';
import 'package:dartpy/dartpy_annotations.dart';
part 'gen_dartpy_example.g.dart';

@PyFunction(module: 'multiply')
int multiply(int a, int b) => pymultiply(a, b);

@PyFunction(module: 'multiply', name: 'multiply')
double mult_double(double a, double b) => pymultiplydouble(a, b);

@PyFunction(module: 'multiply', name: 'multiply')
num mult_num(num a, num b) => pymultiplynum(a, b);

void main() {
  try {
    print(multiply(6, 4));
    print(mult_double(6.13, 5.2));
    print(mult_num(6, 5.2));
    print(mult_num(6, 2));
  } on DartPyException catch (e) {
    if (pyErrOccurred()) {
      dartpyc.PyErr_Print();
    }
    print(e.message);
  }
}

"Python" is a registered trademark of the Python Software Foundation

About

An experiment in embedding Python in Dart via dart ffi and the Python c-api

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages