Hi guys,
I want to make a simple Python3 extension in Nim. I used the Nim Backend Integration (http://nim-lang.org/docs/backends.html#interfacing-backend-code-calling-nim) example as a starting point.
The example crashes when trying to echo the arguments passed from the C wrapper to the Nim procedure in the nim_module.nim file line 5. When commenting out that line the extension module works! Can anyone tell me why?
I'm using Windows Vista x64, Python 3.4.1 x64, Nim 0.14.3 x64.
Compiling everything with MSVC 2010.
The Nim file nim_module.nim:
import math
proc cos_func*(number: cdouble): cdouble {.exportc.} =
echo "You're in Nim!"
echo number # <-- This line crashes Python
result = math.cos(number)
It's compiled with nim c --noMain --noLinking --header:nim_module.h nim_module.nim
The Python wrapper file nim_wrapper.c:
#include <stdio.h>
#include <Python.h>
#include "nim_module.h"
/* wrapped cosine function */
static PyObject* first_func(PyObject* self, PyObject* args)
{
double value;
double answer;
/* parse the input, from python float to c double */
if (!PyArg_ParseTuple(args, "d", &value))
return NULL;
/* if the above function returns -1, an appropriate Python exception will
* have been set, and the function simply returns NULL
*/
/* call cos in Nim */
answer = cos_func(value);
/* construct the output from cos, from c double to python float */
return Py_BuildValue("f", answer);
}
/* define functions in module */
static PyMethodDef nim_methods[] =
{
{"first_func", first_func, METH_VARARGS, "evaluate the cosine in Nim"},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef nim_module =
{
PyModuleDef_HEAD_INIT,
"nim_wrapper", /* name of module */
"", /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
nim_methods
};
/* module initialization */
PyMODINIT_FUNC
PyInit_nim_wrapper(void)
{
return PyModule_Create(&nim_module);
}
and the setup.py script:
import os
from distutils.core import setup, Extension
nim_c_files = []
items = os.listdir("nimcache/")
for i in items:
if i.endswith(".c"):
nim_c_files.append("nimcache/" + i)
nim_module = Extension(
'nim_wrapper',
sources = [
'nim_wrapper.c',
] + nim_c_files,
extra_compile_args = [
"-Ipath\\to\\app\\nimcache",
"-IC:\\Nim\\lib",
],
)
# run the setup
setup(ext_modules=[nim_module])
Building the module with:
python3 setup.py build_ext --inplace
The test script is:
import nim_wrapper
print(nim_wrapper.first_func(100))
I feel like an idiot for not spotting that.
Thanks Araq!