Skip to main content

A library for providing inter-language foreign function interface calls

Project description

A library for providing inter-language foreign function interface calls

Abstract

METACALL Python Port is the port of METACALL to Python Programming Language. With METACALL Python Port you can transparently execute code from Python to any programming language, for example, calling JavaScript, NodeJS, Ruby or C# code from Python.

Install

Install MetaCall binaries first:

curl -sL https://raw.githubusercontent.com/metacall/install/master/install.sh | bash

Then install MetaCall Python package through MetaCall:

pip3 install metacall

Example

Calling Ruby from Python

multiply.rb

def multiply(left, right)
    return left * right
end

main.py

from metacall import metacall_load_from_file, metacall

metacall_load_from_file('rb', [ 'multiply.rb' ])

metacall('multiply', 3, 4); # 12

Calling NodeJS from Python (MonkeyPatch API)

sum.js

module.exports = {
    sum: (x, y) => x + y,
};

main.py

import metacall
from sum.js import sum

sum(3, 4); # 7

Running the example:

python3 main.py

Using pointers (calling to a C library)

For a simple case, let’s imagine that we have a simple C function that has an ‘in’ parameter and we want to pass a pointer to a long, from Python side, and then store some value there for reading it later on. Let’s assume we have a loadtest.h and libloadtest.so and a C function from this library could be this one:

void modify_int_ptr(long *l)
{
    *l = 111;
}

Now if we want to call it from Python side, we should do the following:

from metacall import metacall_load_from_package, metacall, metacall_value_reference, metacall_value_dereference

# Load the library (we can configure the search paths for the .so and .lib with metacall_execution_path)
# metacall_execution_path('c', '/usr/local/include')
# metacall_execution_path('c', '/usr/local/lib')
metacall_load_from_package('c', 'loadtest')

# Create value pointer (int *)
int_val = 324444
int_val_ref = metacall_value_reference(int_val)

# Pass the pointer to the function
metacall('modify_int_ptr', int_val_ref)

# Get the value from pointer
int_val_deref = metacall_value_dereference(int_val_ref)
print(int_val_deref, '==', 111)

For a more complex case, where we have an in/out parameter, for example an opaque struct that we want to alloc from C side. First of all, with the following header loadtest.h:

#ifndef LIB_LOAD_TEST_H
#define LIB_LOAD_TEST_H 1

#if defined(WIN32) || defined(_WIN32)
    #define EXPORT __declspec(dllexport)
#else
    #define EXPORT __attribute__((visibility("default")))
#endif

#ifdef __cplusplus
extern "C" {
#endif

#include <cstdint>

typedef struct
{
    uint32_t i;
    double d;
} pair;

typedef struct
{
    uint32_t size;
    pair *pairs;
} pair_list;

EXPORT int pair_list_init(pair_list **t);

EXPORT double pair_list_value(pair_list *t, uint32_t id);

EXPORT void pair_list_destroy(pair_list *t);

#ifdef __cplusplus
}
#endif

#endif /* LIB_LOAD_TEST_H */

With the following implementation loadtest.cpp:

#include "loadtest.h"

int pair_list_init(pair_list **t)
{
    static const uint32_t size = 3;

    *t = new pair_list();

    (*t)->size = size;
    (*t)->pairs = new pair[(*t)->size];

    for (uint32_t i = 0; i < size; ++i)
    {
        (*t)->pairs[i].i = i;
        (*t)->pairs[i].d = (double)(((double)i) * 1.0);
    }

    return 0;
}

double pair_list_value(pair_list *t, uint32_t id)
{
    return t->pairs[id].d;
}

void pair_list_destroy(pair_list *t)
{
    delete[] t->pairs;
    delete t;
}

In this case the structs are not opaque, but they can be opaque and it will work in the same way. Now, we can call those functions in the following manner:

from metacall import metacall_load_from_package, metacall, metacall_value_create_ptr, metacall_value_reference, metacall_value_dereference

metacall_load_from_package('c', 'loadtest')

# Create a pointer to void* set to NULL
list_pair = metacall_value_create_ptr(None)

# Create a reference to it (void**)
list_pair_ref = metacall_value_reference(list_pair)

# Call the function
result = metacall('pair_list_init', list_pair_ref)

# Get the result updated (struct allocated)
list_pair = metacall_value_dereference(list_pair_ref)

# Pass it to a function
result = metacall('pair_list_value', list_pair, 2)

# Destroy it
metacall('pair_list_destroy', list_pair)

# Here result will be 2.0 because is the third element in the array of pairs inside the struct
print(result, '==', 2.0)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

metacall-0.5.4.tar.gz (10.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

metacall-0.5.4-py3-none-any.whl (7.8 kB view details)

Uploaded Python 3

File details

Details for the file metacall-0.5.4.tar.gz.

File metadata

  • Download URL: metacall-0.5.4.tar.gz
  • Upload date:
  • Size: 10.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for metacall-0.5.4.tar.gz
Algorithm Hash digest
SHA256 53adc86f1d60c78ddca65decbfd0dba98d5b0487166e23381e9caf67d7307d85
MD5 032a9faacb96ac303e67687e817ae935
BLAKE2b-256 6e58ce37eb2c2af8af85cb9f7d77d609b25ad82a95ad5705eb41681c848161c9

See more details on using hashes here.

File details

Details for the file metacall-0.5.4-py3-none-any.whl.

File metadata

  • Download URL: metacall-0.5.4-py3-none-any.whl
  • Upload date:
  • Size: 7.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for metacall-0.5.4-py3-none-any.whl
Algorithm Hash digest
SHA256 2b818f2c84a8e727b3a1b476134122c5db74cca13d3f76394c91926923df1185
MD5 ac1ff6b58bb410f3fd78731f9769b3b7
BLAKE2b-256 5eaa941478e5fecaaa44ff9964e66927913b5c853d69b2991a45b05ba2d6c306

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page