Skip to content

Commit

Permalink
add more julia function
Browse files Browse the repository at this point in the history
  • Loading branch information
songjhaha committed Sep 14, 2023
1 parent b658325 commit dff137d
Show file tree
Hide file tree
Showing 11 changed files with 561 additions and 187 deletions.
10 changes: 3 additions & 7 deletions libjuliacall/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,18 @@ if [ -z "$libpython_files" ]; then
fi

# replace it with your include
include_dir=""
include_dir="C:/Users/TR/AppData/Local/miniforge3/include"

if [ -z "$include_dir" ]; then
echo "error! python include not set, please set it in build.sh"
exit 1
fi

lib_dir=$(dirname "$libpython_files")
full_basename=$(basename "$libpython_files")
libpython="${full_basename%.*}"
echo "libpython: $libpython"

echo "lib_dir: $lib_dir"
echo "include_dir: $include_dir"



g++ -fPIC -shared juliacall.cpp -o libjuliacall.dll -I./include -I$include_dir -L$lib_dir -l$libpython
g++ -fPIC -shared juliacall.cpp -o libjuliacall.dll -I./include -I$include_dir -L$lib_dir -lpython3
cp libjuliacall.dll ../tyjuliasetup/src/libjuliacall.dll

261 changes: 234 additions & 27 deletions libjuliacall/include/TyPython.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,50 @@
#include <common.hpp>
#include <assert.h>

ErrorCode py_cast(JV *out, JV T, PyObject* py)
static void PyCapsule_Destruct_JuliaAsPython(PyObject *capsule)
{
JV args[2];
// destruct of capsule(__jlslot__)
JV *jv = (JV *)PyCapsule_GetPointer(capsule, NULL);
JLFreeFromMe(*jv);
free(jv);
}

JV jlpy = to_JLPy(py);
static PyObject *box_julia(JV jv)
{
// JV(julia value) -> PyObject(python's JV with __jlslot__)
if (jv == JV_NULL)
{
PyErr_SetString(PyExc_RuntimeError, "box_julia: failed to create a new instance of JV");
return NULL;
}

args[0] = T;
args[1] = jlpy;
ErrorCode ret = JLCall(out, MyJLAPI.f_TyPython_py_cast, SList_adapt(args, 2), emptyKwArgs());
if (ret != ErrorCode::ok)
{
char errorBytes[2048] = {(char)0};
if (ErrorCode::ok == JLError_FetchMsgStr(&errorSym, SList_adapt(reinterpret_cast<uint8_t *>(errorBytes), sizeof(errorBytes))))
{
PyErr_SetString(JuliaCallError, errorBytes);
}
else
{
PyErr_SetString(JuliaCallError, "juliacall: unknown error");
}
}
JLFreeFromMe(jlpy);
return ret;
JV *ptr_boxed = (JV *)malloc(sizeof(JV));
*ptr_boxed = jv;

PyObject *capsule = PyCapsule_New(
ptr_boxed,
NULL,
&PyCapsule_Destruct_JuliaAsPython);

PyObject *pyjv = PyObject_CallObject(MyPyAPI.t_JV, NULL);
if (pyjv == NULL)
{
PyErr_SetString(PyExc_RuntimeError, "box_julia: failed to create a new instance of JV");
return NULL;
}

PyObject_SetAttr(pyjv, name_jlslot, capsule);
return pyjv;
}

static JV unbox_julia(PyObject *pyjv)
{
// assume pyjv is a python's JV instance with __jlslot__
PyObject *capsule = PyObject_GetAttr(pyjv, name_jlslot);
JV *jv = (JV *)PyCapsule_GetPointer(capsule, NULL);
Py_DecRef(capsule);
return *jv;
}

ErrorCode TOJLInt64FromPy(JV *out, PyObject* py)
{
Expand All @@ -43,7 +62,6 @@ ErrorCode TOJLInt64FromPy(JV *out, PyObject* py)
return ErrorCode::ok;
}


ErrorCode ToJLFloat64FromPy(JV *out, PyObject* py)
{
double i = PyFloat_AsDouble(py);
Expand Down Expand Up @@ -73,16 +91,205 @@ ErrorCode ToJLBoolFromPy(JV *out, PyObject* py)
return ErrorCode::ok;
}

// ErrorCode ToJLComplexFromPy(JV *out, PyObject* py)
ErrorCode ToJLComplexFromPy(JV *out, PyObject* py)
{
double re = PyComplex_RealAsDouble(py);
if (re == -1.0 && PyErr_Occurred() != NULL)
return ErrorCode::error;

double im = PyComplex_ImagAsDouble(py);
if (im == -1.0 && PyErr_Occurred() != NULL)
return ErrorCode::error;

ToJLComplexF64(out, complex_t{re, im});
return ErrorCode::ok;
}

ErrorCode ToJLStringFromPy(JV *out, PyObject* py)
{
Py_ssize_t len;
const char* str = PyUnicode_AsUTF8AndSize(py, &len);
if (str == NULL)
return ErrorCode::error;

ToJLString(out, SList_adapt(reinterpret_cast<uint8_t *>(const_cast<char *>(str)), len));
return ErrorCode::ok;
}

ErrorCode ToJLNothingFromPy(JV *out, PyObject* py)
{
if (py != Py_None)
return ErrorCode::error;
else
{
*out = MyJLAPI.obj_nothing;
return ErrorCode::ok;
}
}

JV reasonable_unbox(PyObject* py)
{
if (py == Py_None)
return MyJLAPI.obj_nothing;

if (PyObject_IsInstance(py, MyPyAPI.t_JV))
return unbox_julia(py);

JV out;
if (PyObject_IsInstance(py, MyPyAPI.t_int))
{
TOJLInt64FromPy(&out, py);
return out;
}

if (PyObject_IsInstance(py, MyPyAPI.t_float))
{
ToJLFloat64FromPy(&out, py);
return out;
}

if (PyObject_IsInstance(py, MyPyAPI.t_str))
{
ToJLStringFromPy(&out, py);
return out;
}

if (PyObject_IsInstance(py, MyPyAPI.t_bool))
{
ToJLBoolFromPy(&out, py);
return out;
}

if (PyObject_IsInstance(py, MyPyAPI.t_complex))
{
ToJLComplexFromPy(&out, py);
return out;
}

if (PyObject_IsInstance(py, MyPyAPI.t_ndarray))
{
ErrorCode ret = pycast2jl(&out, MyJLAPI.t_AbstractArray, py);
if (ret == ErrorCode::ok)
{
return out;
}
else
{
// todo: string array
}
}

// todo: python's tuple

PyErr_SetString(JuliaCallError, "unbox failed: cannot convert a Python object to Julia object");
return JV_NULL;
}

// PyObject* UnsafePyLongFromJL(JV jv)
// {
// Py_complex i = PyComplex_AsCComplex(py);
// if (i.real == -1.0 && PyErr_Occurred() != NULL)
// return ErrorCode::error;
// int64_t i;
// JLGetInt64(&i, jv, true);
// return PyLong_FromLongLong(i);
// }

// ToJLComplexF64(out, reinterpret_cast<complex_t>(i));
// return ErrorCode::ok;
// PyObject* UnsafePyDoubleFromJL(JV jv)
// {
// double i;
// JLGetDouble(&i, jv, true);
// return PyFloat_FromDouble(i);
// }

// PyObject* UnsafePyBoolFromJL(JV jv)
// {
// bool8_t i;
// JLGetBool(&i, jv, true);
// return PyBool_FromLong(i);
// }

// PyObject* UnsafePyStringFromJL(JV jv)
// {
// JV ncode;
// JLCall(&ncode, MyJLAPI.f_ncodeunits, SList_adapt(&jv, 1), emptyKwArgs());
// int64_t len;
// JLGetInt64(&len, ncode, true);
// JLFreeFromMe(ncode);

// if (len == 0)
// return PyUnicode_FromString("");
// else
// {
// // this copy the string twice
// char *buf = (char *)malloc(len + 1);
// JLGetUTF8String(SList_adapt(reinterpret_cast<uint8_t *>(const_cast<char *>(buf)), len), jv);
// buf[len] = '\0';
// PyObject* str = PyUnicode_FromString(buf);
// free(buf);
// return str;
// }
// }


PyObject * reasonable_box(JV jv)
{
PyObject* py;

if (JLIsInstanceWithTypeSlot(jv, MyJLAPI.t_Nothing))
{
Py_IncRef(Py_None);
return Py_None;
}

if (JLIsInstanceWithTypeSlot(jv, MyJLAPI.t_Integer))
{
py = pycast2py(jv);
return py;
}

if (JLIsInstanceWithTypeSlot(jv, MyJLAPI.t_AbstractFloat))
{
py = pycast2py(jv);
return py;
}

if (JLIsInstanceWithTypeSlot(jv, MyJLAPI.t_Bool))
{
py = pycast2py(jv);
return py;
}

if (JLIsInstanceWithTypeSlot(jv, MyJLAPI.t_Complex))
{
py = pycast2py(jv);
return py;
}

if (JLIsInstanceWithTypeSlot(jv, MyJLAPI.t_String))
{
py = pycast2py(jv);
return py;
}

if (JLIsInstanceWithTypeSlot(jv, MyJLAPI.t_AbstractArray))
{
// todo
if (JLIsInstanceWithTypeSlot(jv, MyJLAPI.t_BitArray))
{
py = box_julia(jv);
}
else
{
py = pycast2py(jv);
if (py == NULL) /* on fail */
py = box_julia(jv);
}
return py;
}

// todo: tuple

return box_julia(jv);
}

#endif


Expand Down
Loading

0 comments on commit dff137d

Please sign in to comment.