I'm trying to wrap a c++ function that uses Armadillo library using pybind11 and cppimport. But when I try to do something simple like matrix multiplication I get the following error.
error: no matching function for call to ‘pybind11::buffer_info::buffer_info(double*, long unsigned int, std::__cxx11::string, int, <brace-enclosed initializer list>, <brace-enclosed initializer list>)’
);
^
In file included from /home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/pytypes.h:13:0,
from /home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/cast.h:13,
from /home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/attr.h:13,
from /home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/pybind11.h:43,
from /home/muah/Music/cpp2py/.rendered.code.cpp:3:
/home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/buffer_info.h:83:5: note: candidate: pybind11::buffer_info::buffer_info(pybind11::buffer_info::private_ctr_tag, void*, pybind11::ssize_t, const string&, pybind11::ssize_t, pybind11::detail::any_container<long int>&&, pybind11::detail::any_container<long int>&&)
buffer_info(private_ctr_tag, void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim,
^~~~~~~~~~~
/home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/buffer_info.h:83:5: note: candidate expects 7 arguments, 6 provided
/home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/buffer_info.h:59:5: note: candidate: pybind11::buffer_info::buffer_info(pybind11::buffer_info&&)
buffer_info(buffer_info &&other) {
This is the code for conversions between armadillo mat to numpy vice versa.
#pragma once
#include <armadillo>
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
namespace py=pybind11;
typedef py::array_t<double, py::array::f_style | py::array::forcecast> pyarr_d;
inline
arma::mat py_to_mat(pyarr_d& pmat)
{
py::buffer_info info = pmat.request();
arma::mat amat;
if(info.ndim == 1) {
amat = arma::mat(reinterpret_cast<double*>(info.ptr),info.shape[0],1);
} else {
amat = arma::mat(reinterpret_cast<double*>(info.ptr),info.shape[0],info.shape[1]);
}
return amat;
}
inline
py::array_t<double> mat_to_py(arma::mat &mat)
{
py::buffer_info buffer(
mat.memptr(),
sizeof(double),
py::format_descriptor<double>::format(),
2,
{ mat.n_rows, mat.n_cols },
{ sizeof(double), sizeof(double) * mat.n_rows }
);
return py::array_t<double>(buffer);
}
This is the c++ function:
<%
cfg['compiler_args'] = ['-std=c++11', '-larmadillo']
setup_pybind11(cfg)
%>
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <armadillo>
#include "py2arma.hpp"
namespace py = pybind11;
py::array matrix_mul(pyarr_d a, pyarr_d b)
{
arma::mat A = py_to_mat(a);
arma::mat B = py_to_mat(b);
arma::mat C = A * B;
return mat_to_py(C);
}
PYBIND11_PLUGIN(code)
{
py::module m("code", "lala");
m.def("matrix_mul",(py::array(*)(pyarr_d,pyarr_d))&matrix_mul);
return m.ptr();
}
This is the python function:
import cppimport
import numpy as np
code = cppimport.imp("code")
if __name__ == '__main__':
xs = np.random.rand(3,3)
ys = np.random.rand(3,1)
py_mul = np.dot(xs, ys)
cpp_mul = code.matrix_mul(xs, ys)
print(py_mul)
print(cpp_mul)
This link contains the full stack-trace: https://pastebin.com/XuKyQDMQ
I don't understand what this error means. How to fix this, am I doing the conversions correctly ?
EDIT: To fix the problems, add py::detail::any_container before matrix shape and strides part of buffer_info. And change the type of mat_to_py function from py::array to pyarr_d.
This fixes all the issues with the code.
From tracing from the above comments, seems like it's due to this snippet from your backtrace (line 59):
/home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/buffer_info.h:28:5: note: candidate: pybind11::buffer_info::buffer_info(void*, pybind11::ssize_t, const string&, pybind11::ssize_t, pybind11::detail::any_container<long int>, pybind11::detail::any_container<long int>)
buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim,
^~~~~~~~~~~
/home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/buffer_info.h:28:5: note: no known conversion for argument 6 from ‘<brace-enclosed initializer list>’ to ‘pybind11::detail::any_container<long int>’
My suggestion would be to make this work by first explicitly constructing py::any_container<size_t>(...) for those arguments, which will help you narrow down where inference is going awry. Perhaps it's due to a mismatch between Armadillo's dimensions and ssize_t from pybind11?
I am trying to implement the FIPS_mode and FIPS_mode_set functions in Python's ssl module since those are not present by default. A patch for Python 3.4 has already been submitted and rejected due to various using reasons.
Using that patch as an inspiration, i made some modifications and added the following code in ssl.py:
try:
from _ssl import FIPS_mode, FIPS_mode_set
except ImportError:
pass
And the following code in _ssl.c:
#define EXPORT_FIPSMODE_FUNCS
#ifdef EXPORT_FIPSMODE_FUNCS
static PyObject *
_ssl_FIPS_mode_impl(PyObject *module) {
return PyLong_FromLong(FIPS_mode());
}
static PyObject *
_ssl_FIPS_mode_set_impl(PyObject *module, int n) {
if (FIPS_mode_set(n) == 0) {
_setSSLError(ERR_error_string(ERR_get_error(), NULL) , 0, __FILE__, __LINE__);
return NULL;
}
Py_RETURN_NONE;
}
#endif //EXPORT_FIPSMODE_FUNCS
/* List of functions exported by this module. */
static PyMethodDef PySSL_methods[] = {
_SSL__TEST_DECODE_CERT_METHODDEF
_SSL_RAND_ADD_METHODDEF
_SSL_RAND_BYTES_METHODDEF
_SSL_RAND_PSEUDO_BYTES_METHODDEF
_SSL_RAND_EGD_METHODDEF
_SSL_RAND_STATUS_METHODDEF
_SSL_GET_DEFAULT_VERIFY_PATHS_METHODDEF
_SSL_ENUM_CERTIFICATES_METHODDEF
_SSL_ENUM_CRLS_METHODDEF
_SSL_TXT2OBJ_METHODDEF
_SSL_NID2OBJ_METHODDEF
_SSL_FIPS_MODE_SET_METHODDEF
_SSL_FIPS_MODE_METHODDEF
{NULL, NULL} /* Sentinel */
};
This however is throwing the following errors:
./Modules/_ssl.c:5060:5: error: '_SSL_FIPS_MODE_SET_METHODDEF' undeclared here (not in a function)
_SSL_FIPS_MODE_SET_METHODDEF
./Modules/_ssl.c:5061:5: error: expected '}' before '_SSL_FIPS_MODE_METHODDEF'
_SSL_FIPS_MODE_METHODDEF
./Modules/_ssl.c:4641:1: warning: '_ssl_FIPS_mode_impl' defined but not used [-Wunused-function] _ssl_FIPS_mode_impl(PyObject
*module) {
./Modules/_ssl.c:4646:1: warning: '_ssl_FIPS_mode_set_impl' defined but not used [-Wunused-function]
_ssl_FIPS_mode_set_impl(PyObject *module, int n) { ^
I am pretty sure i am missing something extremely trivial here but i cant seem to figure out what exactly. Any help would be appreciated! Thanks!
Update:
A big shoutout to #CristiFati who pointed out that i was missing the macros which needed to be defined, I was able to solve this. In case someone else needs to implement FIPS Mode in Python 3.6, add the following code:
_ssl.c:
static PyObject *
_ssl_FIPS_mode_impl(PyObject *module) {
return PyLong_FromLong(FIPS_mode());
}
static PyObject *
_ssl_FIPS_mode_set_impl(PyObject *module, int n) {
if (FIPS_mode_set(n) == 0) {
_setSSLError(ERR_error_string(ERR_get_error(), NULL) , 0, __FILE__, __LINE__);
return NULL;
}
Py_RETURN_NONE;
}
static PyMethodDef PySSL_methods[] = {
_SSL__TEST_DECODE_CERT_METHODDEF
_SSL_RAND_ADD_METHODDEF
_SSL_RAND_BYTES_METHODDEF
_SSL_RAND_PSEUDO_BYTES_METHODDEF
_SSL_RAND_EGD_METHODDEF
_SSL_RAND_STATUS_METHODDEF
_SSL_GET_DEFAULT_VERIFY_PATHS_METHODDEF
_SSL_ENUM_CERTIFICATES_METHODDEF
_SSL_ENUM_CRLS_METHODDEF
_SSL_TXT2OBJ_METHODDEF
_SSL_NID2OBJ_METHODDEF
_SSL_FIPS_MODE_METHODDEF
_SSL_FIPS_MODE_SET_METHODDEF
{NULL, NULL} /* Sentinel */
};
_ssl.c.h:
PyDoc_STRVAR(_ssl_FIPS_mode__doc__,
"FIPS Mode");
#define _SSL_FIPS_MODE_METHODDEF \
{"FIPS_mode", (PyCFunction)_ssl_FIPS_mode, METH_NOARGS, _ssl_FIPS_mode__doc__},
static PyObject *
_ssl_FIPS_mode_impl(PyObject *module);
static PyObject *
_ssl_FIPS_mode(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return _ssl_FIPS_mode_impl(module);
}
PyDoc_STRVAR(_ssl_FIPS_mode_set_doc__,
"FIPS Mode Set");
#define _SSL_FIPS_MODE_SET_METHODDEF \
{"FIPS_mode_set", (PyCFunction)_ssl_FIPS_mode_set, METH_O, _ssl_FIPS_mode_set_doc__},
static PyObject *
_ssl_FIPS_mode_set_impl(PyObject *module, int n);
static PyObject *
_ssl_FIPS_mode_set(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
int n;
if (!PyArg_Parse(arg, "i:FIPS_mode_set", &n)) {
goto exit;
}
return_value = _ssl_FIPS_mode_set_impl(module, n);
exit:
return return_value;
}
ssl.py:
try:
from _ssl import FIPS_mode, FIPS_mode_set
print('successful import')
except ImportError as e:
print('error in importing')
print(e)
Looking at the source code, I noticed that since Python 3.5, the ${PYTHON_SRC_DIR}/Modules/_ssl.c structure has changed (got "a little bit" more structured and also contains generated code), compared to the 3.4 version that I submitted the patch to ([Python.Bugs]: FIPS_mode() and FIPS_mode_set() functions in Python (ssl)). Basically, every entry in the PySSL_methods array is no longer defined on the spot, but indirectly, via a preprocessor macro. You acted according to the new standard, but forgot to define the macros.
In order to fix the problem:
Define the 2 macros for the PyMethodDef entries (inside #ifdef EXPORT_FIPSMODE_FUNCS):
// ...
}
#define _SSL_FIPS_MODE_METHODDEF \
{"FIPS_mode", (PyCFunction)_ssl_FIPS_mode_impl, METH_NOARGS, NULL},
#define _SSL_FIPS_MODE_SET_METHODDEF \
{"FIPS_mode_set", (PyCFunction)_ssl_FIPS_mode_set_impl, METH_O, NULL},
#endif // EXPORT_FIPSMODE_FUNCS
// ...
"Protect" the new macros by an #ifdef clause (similarly to where they were defined) when defining PySSL_methods (so that if the EXPORT_FIPSMODE_FUNCS macro isn't defined, you won't get a compile error):
// ...
_SSL_NID2OBJ_METHODDEF
#ifdef EXPORT_FIPSMODE_FUNCS
_SSL_FIPS_MODE_METHODDEF
_SSL_FIPS_MODE_SET_METHODDEF
#endif // EXPORT_FIPSMODE_FUNCS
{NULL, NULL} /* Sentinel */
// ...
Notes:
Since you didn't define the docstrings, I filled them with NULLs (PyMethodDef's last member). That will result in syntactically correct code, but I'm not sure how will it behave at runtime, when you'll run help() on any of the 2 functions. If it segfaults, copy the definitions from the patch or define some dummy strings using PyDoc_STRVAR (and recompile, of course)
Although this is closer to the standard than the original patch, it's not quite there, as OP (#HussainAliAkbar) shown in the (2nd) edit. Things are a little bit more complicated (also involving ${PYTHON_SRC_DIR}/Modules/clinic/_ssl.c.h). See the next update section below
Update #0
I took some time to check what's the deal with that clinic folder. It's [Python.Docs]: Argument Clinic How-To. I consider it a major improvement because it spares the developer writing the argument parsing code (involving PyArg_*, Py*_Check funcs) in every function ("monkey work")
I spent some hours, but I managed to do things "by the book" (at least, I think so)
Python-3.6.4-ssl_fips.diff:
--- Python-3.6.4/Modules/_ssl.c.orig 2018-07-27 19:10:06.131999999 +0300
+++ Python-3.6.4/Modules/_ssl.c 2018-07-27 20:32:15.531999999 +0300
## -4789,6 +4789,46 ##
return result;
}
+#if defined(EXPORT_FIPSMODE_FUNCS)
+
+unsigned char _fips_table_sig[0x0C] = {0x21, 0x7A, 0x65, 0x6C, 0x75, 0x72, 0x20, 0x49, 0x54, 0x41, 0x46, 0x00};
+
+/*[clinic input]
+_ssl.FIPS_mode
+
+Return 1 (!=0) if FIPS mode is enabled, 0 otherwise.
+[clinic start generated code]*/
+
+static PyObject *
+_ssl_FIPS_mode_impl(PyObject *module)
+/*[clinic end generated code: output=89f5a88ec715a291 input=52e4e5fdd1f555c7]*/
+{
+ return PyLong_FromLong(FIPS_mode());
+}
+
+/*[clinic input]
+_ssl.FIPS_mode_set
+ mode: int
+ /
+
+Try to set the FIPS mode to 'mode' (int).
+
+Return nothing. Raise SSLError when enabling FIPS mode fails.
+[clinic start generated code]*/
+
+static PyObject *
+_ssl_FIPS_mode_set_impl(PyObject *module, int mode)
+/*[clinic end generated code: output=70e3e9f3bb4fce65 input=899c21a986720235]*/
+{
+if (FIPS_mode_set(mode) == 0) {
+ _setSSLError(ERR_error_string(ERR_get_error(), NULL), 0, __FILE__, __LINE__);
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+#endif // EXPORT_FIPSMODE_FUNCS
+
#ifdef _MSC_VER
static PyObject*
## -5055,6 +5095,8 ##
_SSL_ENUM_CRLS_METHODDEF
_SSL_TXT2OBJ_METHODDEF
_SSL_NID2OBJ_METHODDEF
+ _SSL_FIPS_MODE_METHODDEF
+ _SSL_FIPS_MODE_SET_METHODDEF
{NULL, NULL} /* Sentinel */
};
--- Python-3.6.4/Modules/clinic/_ssl.c.h.orig 2018-07-27 19:10:48.067999999 +0300
+++ Python-3.6.4/Modules/clinic/_ssl.c.h 2018-07-27 20:31:04.507999999 +0300
## -1062,6 +1062,61 ##
return return_value;
}
+#if defined(EXPORT_FIPSMODE_FUNCS)
+
+PyDoc_STRVAR(_ssl_FIPS_mode__doc__,
+"FIPS_mode($module, /)\n"
+"--\n"
+"\n"
+"Return 1 (!=0) if FIPS mode is enabled, 0 otherwise.");
+
+#define _SSL_FIPS_MODE_METHODDEF \
+ {"FIPS_mode", (PyCFunction)_ssl_FIPS_mode, METH_NOARGS, _ssl_FIPS_mode__doc__},
+
+static PyObject *
+_ssl_FIPS_mode_impl(PyObject *module);
+
+static PyObject *
+_ssl_FIPS_mode(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _ssl_FIPS_mode_impl(module);
+}
+
+#endif /* defined(EXPORT_FIPSMODE_FUNCS) */
+
+#if defined(EXPORT_FIPSMODE_FUNCS)
+
+PyDoc_STRVAR(_ssl_FIPS_mode_set__doc__,
+"FIPS_mode_set($module, mode, /)\n"
+"--\n"
+"\n"
+"Try to set the FIPS mode to \'mode\' (int).\n"
+"\n"
+"Return nothing. Raise SSLError when enabling FIPS mode fails.");
+
+#define _SSL_FIPS_MODE_SET_METHODDEF \
+ {"FIPS_mode_set", (PyCFunction)_ssl_FIPS_mode_set, METH_O, _ssl_FIPS_mode_set__doc__},
+
+static PyObject *
+_ssl_FIPS_mode_set_impl(PyObject *module, int mode);
+
+static PyObject *
+_ssl_FIPS_mode_set(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ int mode;
+
+ if (!PyArg_Parse(arg, "i:FIPS_mode_set", &mode)) {
+ goto exit;
+ }
+ return_value = _ssl_FIPS_mode_set_impl(module, mode);
+
+exit:
+ return return_value;
+}
+
+#endif /* defined(EXPORT_FIPSMODE_FUNCS) */
+
#if defined(_MSC_VER)
PyDoc_STRVAR(_ssl_enum_certificates__doc__,
## -1161,6 +1216,14 ##
#define _SSL_RAND_EGD_METHODDEF
#endif /* !defined(_SSL_RAND_EGD_METHODDEF) */
+#ifndef _SSL_FIPS_MODE_METHODDEF
+ #define _SSL_FIPS_MODE_METHODDEF
+#endif /* !defined(_SSL_FIPS_MODE_METHODDEF) */
+
+#ifndef _SSL_FIPS_MODE_SET_METHODDEF
+ #define _SSL_FIPS_MODE_SET_METHODDEF
+#endif /* !defined(_SSL_FIPS_MODE_SET_METHODDEF) */
+
#ifndef _SSL_ENUM_CERTIFICATES_METHODDEF
#define _SSL_ENUM_CERTIFICATES_METHODDEF
#endif /* !defined(_SSL_ENUM_CERTIFICATES_METHODDEF) */
## -1168,4 +1231,4 ##
#ifndef _SSL_ENUM_CRLS_METHODDEF
#define _SSL_ENUM_CRLS_METHODDEF
#endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */
-/*[clinic end generated code: output=a8b184655068c238 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=94d0ec4213d44124 input=a9049054013a1b77]*/
--- Python-3.6.4/Lib/ssl.py.orig 2018-07-27 19:10:29.827999999 +0300
+++ Python-3.6.4/Lib/ssl.py 2018-03-28 23:30:35.065667344 +0300
## -114,6 +114,11 ##
# LibreSSL does not provide RAND_egd
pass
+try:
+ from _ssl import FIPS_mode, FIPS_mode_set
+except ImportError:
+ # Compiled without FIPS functions support
+ pass
from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_TLSv1_3
from _ssl import _OPENSSL_API_VERSION
--- Python-3.6.4/setup.py.orig 2018-07-27 19:09:33.763999999 +0300
+++ Python-3.6.4/setup.py 2018-03-28 23:30:35.061667315 +0300
## -862,6 +862,7 ##
ssl_libs is not None):
exts.append( Extension('_ssl', ['_ssl.c'],
include_dirs = ssl_incs,
+ define_macros = [("EXPORT_FIPSMODE_FUNCS", None)],
library_dirs = ssl_libs,
libraries = ['ssl', 'crypto'],
depends = ['socketmodule.h']), )
Notes:
That is a diff (note that it's outside ${PYTHON_SRC_DIR}). See [SO]: Run/Debug a Django application's UnitTests from the mouse right click context menu in PyCharm Community Edition? (#CristiFati's answer) (Patching utrunner section) for how to apply patches on Win (basically, every line that starts with one "+" sign goes in, and every line that starts with one "-" sign goes out)
Source baseline is v3.6.4 (as pointed by the file name)
4 files are modified:
${PYTHON_SRC_DIR}/Modules/_ssl.c - contains both manual and generated (as you guessed, by the Argument Clinic) changes (generated pieces easy to spot from comments)
${PYTHON_SRC_DIR}/Modules/clinic/_ssl.c.h - contains generated code only
The other 2 contain manual changes
I also tested the changes (at one point I used the OpenSSL version that I've built for [SO]: How to enable FIPS mode for libcrypto and libssl packaged with Python? (#CristiFati's answer))
Output:
[cfati#cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049493537]> LD_LIBRARY_PATH=./py364-nofips/lib ./py364-nofips/bin/python3 -c "import ssl;print(ssl.FIPS_mode())"
Traceback (most recent call last):
File "<string>", line 1, in <module>
AttributeError: module 'ssl' has no attribute 'FIPS_mode'
[cfati#cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049493537]> LD_LIBRARY_PATH=py364-fips/lib py364-fips/bin/python3 -c "import ssl;print(ssl.FIPS_mode(), ssl.FIPS_mode_set(0), ssl.FIPS_mode());print(ssl.FIPS_mode_set(1), ssl.FIPS_mode())"
0 None 0
Traceback (most recent call last):
File "<string>", line 1, in <module>
ssl.SSLError: error:0F06D065:common libcrypto routines:FIPS_mode_set:fips mode not supported (_ssl.c:4822)
[cfati#cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049493537]> LD_LIBRARY_PATH=py364-fips/lib:../q049320993/ssl/build/lib py364-fips/bin/python3 -c "import ssl;print(ssl.FIPS_mode(), ssl.FIPS_mode_set(0), ssl.FIPS_mode());print(ssl.FIPS_mode_set(1), ssl.FIPS_mode())"
0 None 0
None 1
Might also look over [SO]: OpenSSL FIPS_mode_set not working in Python cryptography library (#CristiFati's answer).
I'm working on a project that need to use lib magic library to detect file mime type, I'm using 64 Bit version for windows (see: https://github.com/nscaife/file-windows) my project itself is C dll which I will call it from python. Loading the library is working fine, however when I use GetProcAddress() to access some function, it return NULL and the GetLastError() function return 126. See my code:
int DLL_EXPORT mag()
{
char *actual_file = "test.db";
const char *magic_full;
HMODULE hModule = LoadLibrary("libmagic-1.dll");
if(hModule == NULL) //No problem here
return GetLastError();
magic_t (*t0)(int) = (void *) GetProcAddress(hModule, "magic_open");
const char (*t)(magic_t, const char *) = (void *)
GetProcAddress(hModule, "magic_file");
if(t0 == NULL && t == NULL);
return GetLastError();
magic_t magic_cookie;
magic_cookie = t0(MAGIC_MIME);
magic_full = t(magic_cookie, actual_file);
return 0;
}
What is the problem Here?
I have a struct called Spiketimesolver defined in the following header file:
#include <math.h>
#include "plot_support.h"
struct Spiketimesolver {
const Doub tau_0, I_0, V_start, I_start;
Spiketimesolver(const Doub tau_0, const Doub I_0, const Doub V_start,
const Doub I_start) :
tau_0(tau_0), I_0(I_0), V_start(V_start), I_start(I_start)
{}
Doub operator()(const Doub t) {
const Doub I = get_I(I_start, t, tau_0);
const Doub V = get_V(I_start, t, tau_0, I_0, V_start, I);
return 0.5 * pow((V - 1), 2);
}
};
(get_I and get_V are defined in my file plot_support.h. Their definitions are irrelevant here.)
In a separate module, I instantiate this struct as follows:
Spiketimesolver solver(tau_0, I_0, V_start, I_start);
Here, all the arguments are doubles.
I want to pass solver to a function I have defined thus:
template<class T> PyObject* NRpyObject(T &a) {
// default applies to all function objects or other structs
PyObject *thing = PyCapsule_New((void*)a,NULL,NULL);
return thing;
}
PyCapsule_New is part of the Python C API. It expects void *pointer as the first argument.
When I try to compile, I get the following error for the call NRpyObject(solver):
In file included from analysis_cmodule.cpp:2:0:
nr3python.h: In instantiation of ‘PyObject* NRpyObject(T&) [with T = Spiketimesolver; PyObject = _object]’:
analysis_cmodule.cpp:16:27: required from here
nr3python.h:183:52: error: invalid cast from type ‘Spiketimesolver’ to type ‘void*’
PyObject *thing = PyCapsule_New((void*)a,NULL,NULL);
^
What have I done wrong?
The first argument to PyCapsule_New needs to be a pointer. You are trying to accomplish that by casting a to void*. However, the compiler does not like that. I am guessing that you need to use:
PyObject *thing = PyCapsule_New(&a,NULL,NULL);
I am getting an error on a specific line that mimics the usage in another file.
PyObject *pyCharGetHeight(PyChar *self, void *closure) {
CHAR_DATA *ch = PyChar_AsChar((PyObject *)self);
PyObject *height = NULL;
if(ch != NULL) height = Py_BuildValue("s", charGetHeight(ch));
return height;
}
PyChar_addGetSetter("height", pyCharGetHeight, NULL, "Returns character's height");
is returning the following error, PyChar_addGetSetter... line
error: expected declaration specifiers or â...â before string constant
I am using the following includes:
#include <Python.h>
#include "../scripts/pychar.h"
And pychar.h does define PyChar_addGetSetter() as prototyped here:
void PyChar_addGetSetter(const char *name, void *g, void *s, const char *doc);
The function is written in ../scripts/pychar.c as follows:
void PyChar_addGetSetter(const char *name, void *g, void *s, const char *doc) {
// make sure our list of get/setters is created
if(pychar_getsetters == NULL) pychar_getsetters = newList();
// make the GetSetter def
PyGetSetDef *def = calloc(1, sizeof(PyGetSetDef));
def->name = strdup(name);
def->get = (getter)g;
def->set = (setter)s;
def->doc = (doc ? strdup(doc) : NULL);
def->closure = NULL;
listPut(pychar_getsetters, def);
}
It seems like a structure or type is not being recognized, I am guessing my function.
It looks like you're trying to call a function at the top level of a .c file. You can't do that.
The error message could be a little nicer, but it looks like gcc is interpreting this as an attempt to declare a type named PyChar_addGetSetter and/or to declare a global variable of that type, and failing to interpret it either way, and telling you why that attempt failde.