-
Notifications
You must be signed in to change notification settings - Fork 20
Description
I've been attempting to install the ACH module by following the instructions provided on the INSTALL page. Initially, I tried downloading and installing the module using the link provided: http://code.golems.org/src/ach/py_ach-latest.tar.gz. However, it seems that the file is currently not valid, and I'm unable to proceed with the installation using this method.
Subsequently, I followed the instructions on the INSTALL page and attempted to build the setup.py file. However, during this process, I encountered the following error message:
<frozen importlib._bootstrap>:219: RuntimeWarning: Python C API version mismatch for module ach_py: This Python has API version 1013, module ach_py has version -1522732640.
Installation Steps Attempted:
1. Cloned the repository: git clone https://github.com/golems/ach.git
2. Navigated to the ach directory: cd ach
3. Initialized autotools: autoreconf -i
4. Configured the build: ./configure --with-python --enable-dkms=no
5. Executed the build: make
6. Installed the module: sudo make install
7. Navigated to the python directory: cd python
8. Modified the ach_py.c code to adapt it for Python 3 by changing functions like PyInt_AsLong to PyLong_AsLong.
9. Installed the module using Python 3: sudo python3 setup.py install
This is modified ach_py.c
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <Python.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/stat.h>
#include <string.h>
#include <inttypes.h>
#include "ach.h"
PyMODINIT_FUNC PyInit_ach_py(void);
static PyObject *ach_py_error;
static ach_channel_t *parse_channel_pointer( PyObject *i ) {
if( PyLong_Check(i) ) {
return (ach_channel_t*)PyLong_AsLong(i);
} else if ( PyLong_Check(i) ) {
return (ach_channel_t*)PyLong_AsVoidPtr(i);
} else {
PyErr_SetString( PyExc_TypeError, "invalid channel pointer" );
return NULL;
}
}
static PyObject *raise_error( ach_status_t r ) {
PyErr_SetString( ach_py_error, ach_result_to_string(r) );
return NULL;
}
static PyObject *
ach_error( PyObject *self, PyObject *args ) {
(void)self;
int r;
if( !PyArg_ParseTuple(args, "i", &r ) ) {
return NULL;
}
return raise_error((ach_status_t)r);
}
static PyObject *
open_channel( PyObject *self, PyObject *args ) {
(void)self;
const char *name = NULL;
long frame_count = 0, frame_size = 0;
if( !PyArg_ParseTuple(args, "sll", &name, &frame_count, &frame_size ) ) {
return NULL;
}
/* Alloc struct */
ach_channel_t *c = (ach_channel_t*)malloc(sizeof(ach_channel_t));
/* Open it */
ach_status_t r = ach_open(c, name, NULL);
/* Create channel if necessary */
if( ACH_ENOENT == r ) {
r = ach_create( name, (size_t)frame_count, (size_t)frame_size, NULL );
if( ach_status_match(r, ACH_MASK_OK | ACH_MASK_EEXIST) ) {
r = ach_open(c, name, NULL);
}
}
/* Check result */
if( ACH_OK != r ) {
return raise_error(r);
}
return PyLong_FromVoidPtr(c);
}
static PyObject *
close_channel( PyObject *self, PyObject *args ) {
(void)self;
PyObject *py_chan;
if( !PyArg_ParseTuple(args, "O", &py_chan) ) {
return NULL;
}
ach_channel_t *c = parse_channel_pointer(py_chan);
if( NULL == c ) {
return NULL;
}
ach_status_t r = ach_close(c);
if( ACH_OK != r ) {
return raise_error(r);
}
free(c);
Py_RETURN_NONE;
}
static PyObject *
result_string( PyObject *self, PyObject *args ) {
(void)self;
int r;
if( !PyArg_ParseTuple(args, "i", &r ) ) {
return NULL;
}
return PyUnicode_FromString( ach_result_to_string((enum ach_status)r) );
}
static PyObject *
put_buf( PyObject *self, PyObject *args ) {
(void)self;
PyObject *py_chan, *b;
// get arg objects
if( !PyArg_ParseTuple(args, "OO", &py_chan, &b) ) {
return NULL;
}
// parse channel
ach_channel_t *c = parse_channel_pointer(py_chan);
if( NULL == c ) {
return NULL;
}
// parse buffer
if( ! PyObject_CheckBuffer(b) ) {
PyErr_SetString( PyExc_TypeError, "invalid buffer" );
return NULL;
}
// view buffer
Py_buffer buf;
if( PyObject_GetBuffer( b, &buf, PyBUF_SIMPLE ) ) {
PyErr_SetString( PyExc_BufferError, "couldn't view buffer" );
return NULL;
}
// make the damn call
ach_status_t r = ach_put( c, buf.buf, (size_t)buf.len );
// check the result
if( ACH_OK != r ) {
PyErr_SetString( ach_py_error, ach_result_to_string(r) );
return NULL;
}
// cleanup
PyBuffer_Release(&buf);
Py_RETURN_NONE;
}
static PyObject *
get_buf( PyObject *self, PyObject *args ) {
(void)self;
PyObject *py_chan, *b;
int wait, last;
// get arg objects
if( !PyArg_ParseTuple(args, "OOii", &py_chan, &b, &wait, &last) ) {
return NULL;
}
// parse channel
ach_channel_t *c = parse_channel_pointer(py_chan);
if( NULL == c ) {
return NULL;
}
// parse buffer
if( ! PyObject_CheckBuffer(b) ) {
PyErr_SetString( PyExc_TypeError, "invalid buffer" );
return NULL;
}
// view buffer
Py_buffer buf;
if( PyObject_GetBuffer( b, &buf, PyBUF_WRITABLE ) ) {
PyErr_SetString( PyExc_BufferError, "couldn't view writable buffer" );
return NULL;
}
// parse opts
int opts = 0;
if (wait) opts |= ACH_O_WAIT;
if (last) opts |= ACH_O_LAST;
// make the damn call
size_t frame_size;
ach_status_t r = ach_get( c, buf.buf, (size_t)buf.len,
&frame_size, NULL, opts );
// cleanup
PyBuffer_Release(&buf);
// return
switch(r) {
case ACH_OK:
case ACH_STALE_FRAMES:
case ACH_MISSED_FRAME:
case ACH_TIMEOUT:
case ACH_CANCELED:
return Py_BuildValue("ik", r, frame_size);
case ACH_OVERFLOW:
case ACH_INVALID_NAME:
case ACH_BAD_SHM_FILE:
case ACH_FAILED_SYSCALL:
case ACH_CLOSED:
case ACH_EEXIST:
case ACH_ENOENT:
case ACH_BUG:
case ACH_EINVAL:
case ACH_CORRUPT:
case ACH_BAD_HEADER:
case ACH_EACCES:
case ACH_EINTR:
case ACH_EFAULT:
case ACH_ENOTSUP:
return raise_error(r);
}
return NULL;
}
static PyObject *
flush_channel( PyObject *self, PyObject *args ) {
(void)self;
PyObject *py_chan;
// get arg objects
if( !PyArg_ParseTuple(args, "O", &py_chan) ) {
return NULL;
}
// parse channel
ach_channel_t *c = parse_channel_pointer(py_chan);
if( NULL == c ) {
return NULL;
}
// make the damn call
ach_status_t r = ach_flush( c );
// check the result
if( ACH_OK != r ) {
PyErr_SetString( ach_py_error, ach_result_to_string(r) );
return NULL;
}
// cleanup
Py_RETURN_NONE;
}
static PyObject *
chmod_channel( PyObject *self, PyObject *args ) {
(void)self;
PyObject *py_chan;
int mode;
// get arg objects
if( !PyArg_ParseTuple(args, "Oi", &py_chan, &mode) ) {
return NULL;
}
// parse channel
ach_channel_t *c = parse_channel_pointer(py_chan);
if( NULL == c ) {
return NULL;
}
// make the damn call
ach_status_t r = ach_chmod( c, (mode_t)mode );
// check the result
if( ACH_OK != r ) {
PyErr_SetString( ach_py_error, ach_result_to_string(r) );
return NULL;
}
// cleanup
Py_RETURN_NONE;
}
static PyObject *
unlink_channel( PyObject *self, PyObject *args ) {
(void)self;
const char *name;
// get arg objects
if( !PyArg_ParseTuple(args, "s", &name) ) {
return NULL;
}
// make the damn call
ach_status_t r = ach_unlink( name );
// check the result
if( ACH_OK != r ) {
PyErr_SetString( ach_py_error, ach_result_to_string(r) );
return NULL;
}
// cleanup
Py_RETURN_NONE;
}
static PyMethodDef module_methods[] = {
{ "open_channel", (PyCFunction)open_channel, METH_VARARGS, NULL },
{ "close_channel", (PyCFunction)close_channel, METH_VARARGS, NULL },
{ "put_buf", (PyCFunction)put_buf, METH_VARARGS, NULL },
{ "get_buf", (PyCFunction)get_buf, METH_VARARGS, NULL },
{ "ach_error", (PyCFunction)ach_error, METH_VARARGS, NULL },
{ "result_string", (PyCFunction)result_string, METH_VARARGS, NULL },
{ "flush_channel", (PyCFunction)flush_channel, METH_VARARGS, NULL },
{ "chmod_channel", (PyCFunction)chmod_channel, METH_VARARGS, NULL },
{ "unlink_channel", (PyCFunction)unlink_channel, METH_VARARGS, NULL },
{ NULL, NULL, 0, NULL }
};
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"ach_py", /* name of module */
NULL, /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables. */
module_methods
};
PyMODINIT_FUNC PyInit_ach_py(void) {
PyObject *m;
// methods
m = PyModule_Create2(&module, module_methods);
if( NULL == m ) {
return NULL;
}
// error object
static char errname[] = "ach_py.AchException";
ach_py_error = PyErr_NewException( errname, NULL, NULL);
Py_INCREF( ach_py_error ); // Reference counts? Get with the program python!
PyModule_AddObject(m, "AchException", ach_py_error);
// keyword/const objects
PyModule_AddObject( m, "ACH_OK", PyLong_FromLong( ACH_OK ) );
PyModule_AddObject( m, "ACH_OVERFLOW", PyLong_FromLong( ACH_OVERFLOW ) );
PyModule_AddObject( m, "ACH_INVALID_NAME", PyLong_FromLong( ACH_INVALID_NAME ) );
PyModule_AddObject( m, "ACH_BAD_SHM_FILE", PyLong_FromLong( ACH_BAD_SHM_FILE ) );
PyModule_AddObject( m, "ACH_FAILED_SYSCALL", PyLong_FromLong( ACH_FAILED_SYSCALL ) );
PyModule_AddObject( m, "ACH_STALE_FRAMES", PyLong_FromLong( ACH_STALE_FRAMES ) );
PyModule_AddObject( m, "ACH_EAGAIN" , PyLong_FromLong( ACH_EAGAIN ) );
PyModule_AddObject( m, "ACH_LOCKED" , PyLong_FromLong( ACH_LOCKED ) );
PyModule_AddObject( m, "ACH_MISSED_FRAME", PyLong_FromLong( ACH_MISSED_FRAME ) );
PyModule_AddObject( m, "ACH_TIMEOUT", PyLong_FromLong( ACH_TIMEOUT ) );
PyModule_AddObject( m, "ACH_EEXIST", PyLong_FromLong( ACH_EEXIST ) );
PyModule_AddObject( m, "ACH_ENOENT", PyLong_FromLong( ACH_ENOENT ) );
PyModule_AddObject( m, "ACH_CLOSED", PyLong_FromLong( ACH_CLOSED ) );
PyModule_AddObject( m, "ACH_BUG", PyLong_FromLong( ACH_BUG ) );
PyModule_AddObject( m, "ACH_EINVAL", PyLong_FromLong( ACH_EINVAL ) );
PyModule_AddObject( m, "ACH_CORRUPT", PyLong_FromLong( ACH_CORRUPT ) );
PyModule_AddObject( m, "ACH_CANCELED", PyLong_FromLong( ACH_CANCELED ) );
PyModule_AddObject( m, "ACH_BAD_HEADER", PyLong_FromLong( ACH_BAD_HEADER ) );
PyModule_AddObject( m, "ACH_EACCES", PyLong_FromLong( ACH_EACCES ) );
PyModule_AddObject( m, "ACH_O_WAIT", PyLong_FromLong( ACH_O_WAIT ) );
PyModule_AddObject( m, "ACH_O_LAST", PyLong_FromLong( ACH_O_LAST ) );
/* PyModule_AddObject( m, "ACH_DEFAULT_FRAME_SIZE", PyLong_FromLong( ACH_DEFAULT_FRAME_SIZE ) ); */
/* PyModule_AddObject( m, "ACH_DEFAULT_FRAME_COUNT", PyLong_FromLong( ACH_DEFAULT_FRAME_COUNT ) ); */
return m;
}Expected Outcome:
I expected to be able to successfully install the ACH module using the provided source and instructions. However, I encountered the aforementioned error related to the Python C API version mismatch.
Additional Information:
Operating System: x86_64 (amd64)
Python Version: Python 3.8 with anaconda3
Steps to Reproduce:
Clone the ACH repository: git clone https://github.com/golems/ach.git
Follow the installation steps outlined above.
Desired Solution:
I would appreciate any guidance or suggestions on how to resolve the Python C API version mismatch error and successfully install the ACH module.
Thank you for your assistance!