With a regular class BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS works :
>> more dummy.cpp
#include <boost/python.hpp>
using namespace boost::python;
class X
{
public:
X() {};
int twice(int x=5, float y=2.) {return (int)(x*y);};
};
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_twice_overloads, X::twice, 0, 2)
BOOST_PYTHON_MODULE(dummy)
{
class_<X>("X").def("twice", &X::twice, X_twice_overloads(args("x", "y")));
}
>> make
g++ -I /usr/include/python2.7 -o dummy.so -fPIC -shared dummy.cpp -lboost_python -lpython2.7
>> python
Python 2.7.17 (default, Oct 19 2019, 23:36:22)
[GCC 9.2.1 20191008] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import dummy; dx = dummy.X(); print dx.twice(), dx.twice(2,-1.)
10 -2
OK, that works.
Now I need to "templatize" a class with one (only) type T :
>> more dummyT.cpp
#include <string>
#include <boost/python.hpp>
using namespace boost::python;
template<typename T>
class Y
{
public:
Y() {};
T twice(T x=5, float y=2.) {return (T)(x*y);};
};
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(Yint_twice_overloads, Y<int>::twice, 0, 2)
template<typename T, typename O>
void exportY(std::string type)
{
class_<Y<T>>(type.c_str()).def("twice", &Y<T>::twice, O(args("x", "y")));
};
BOOST_PYTHON_MODULE(dummyT)
{
exportY<int, Yint_twice_overloads>("Yint");
}
>> make dummyT
g++ -I /usr/include/python2.7 -o dummyT.so -fPIC -shared dummyT.cpp -lboost_python -lpython2.7
>> python
Python 2.7.17 (default, Oct 19 2019, 23:36:22)
[GCC 9.2.1 20191008] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import dummyT; dy = dummyT.Yint(); print dy.twice(), dy.twice(2,-1.)
10 -2
OK: works fine.
But, now I need to "templatize" a class with 2 types T and U:
>> more dummyTU.cpp
#include <string>
#include <boost/python.hpp>
#include <boost/preprocessor.hpp>
using namespace boost::python;
template<typename T, typename U>
class Z
{
public:
Z() {};
T twice(T x=5, U y=2.) {return (T)(x*y);};
};
#define SEVERAL_ARGS_AS_ONE_EXPAND(a,b) Z<a,b>::twice
#define SEVERAL_ARGS_AS_ONE_EXPAND_EXPAND(a,b) SEVERAL_ARGS_AS_ONE_EXPAND(a,b)
#define SEVERAL_ARGS_AS_ONE(a,b) SEVERAL_ARGS_AS_ONE_EXPAND_EXPAND(a,b)
#define ARGS int, float
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(Zintfloat_twice_overloads, SEVERAL_ARGS_AS_ONE(ARGS), 0, 2)
template<typename T, typename U, typename O>
void exportZ(std::string type)
{
class_<Z<T,U>>(type.c_str()).def("twice", &Z<T,U>::twice, O(args("x", "y")));
};
BOOST_PYTHON_MODULE(dummyTU)
{
exportZ<int, float, Zintfloat_twice_overloads>("Zintfloat");
}
>> make dummyTU
g++ -I /usr/include/python2.7 -o dummyTU.so -fPIC -shared dummyTU.cpp -lboost_python -lpython2.7
dummyTU.cpp:19:98: error: macro "SEVERAL_ARGS_AS_ONE" requires 2 arguments, but only 1 given
19 | BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(Zintfloat_twice_overloads, SEVERAL_ARGS_AS_ONE(ARGS), 0, 2)
This breaks.
As far as I understand the "double macro expand" trick should make "several args as one", but, this seems to fail. Can't get BOOST_PP_XXX to work either. Is there a way to get this to work ?
Solution:
>> more dummyTU.cpp
#include <string>
#include <boost/python.hpp>
using namespace boost::python;
template<typename T, typename U>
class Z
{
public:
Z() {};
T twice(T x=5, U y=2.) {return (T)(x*y);};
};
#define SEVERAL_ARGS_AS_ONE_EXPAND(a,b) Z<a,b>
#define SEVERAL_ARGS_AS_ONE_EXPAND_EXPAND(...) SEVERAL_ARGS_AS_ONE_EXPAND(__VA_ARGS__)
#define SEVERAL_ARGS_AS_ONE(...) SEVERAL_ARGS_AS_ONE_EXPAND_EXPAND(__VA_ARGS__)
#define N_ARGS() int,float
typedef SEVERAL_ARGS_AS_ONE(N_ARGS()) ZintfloatTD;
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(Zintfloat_twice_overloads, ZintfloatTD::twice, 0, 2)
template<typename T, typename U, typename O>
void exportZ(std::string type)
{
class_<Z<T,U>>(type.c_str()).def("twice", &Z<T,U>::twice, O(args("x", "y")));
};
BOOST_PYTHON_MODULE(dummyTU)
{
exportZ<int, float, Zintfloat_twice_overloads>("Zintfloat");
}
>> make dummyTU
g++ -I /usr/include/python2.7 -o dummyTU.so -fPIC -shared dummyTU.cpp -lboost_python -lpython2.7
>> python
Python 2.7.17 (default, Oct 19 2019, 23:36:22)
[GCC 9.2.1 20191008] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import dummyTU; dz = dummyTU.Zintfloat(); print dz.twice(), dz.twice(2,-1.)
10 -2
Related
I want to create some trivial S-function with legacy_code for my MexTest.c:
legacy_code('compile', specs, compilerOptions)
There are 2 macros (TEST_DEF1 and TEST_DEF2), which I want to put into compilerOptions. The 2 macros are used in the function TestFnc().
But somehow, the TestFnc() does not see the 2 macros defined in compilerOptions before...
MexTest.c:
#include "MexTest.h"
void TestFnc(double *p_u, double *p_y)
{
*p_y = *p_u + 1;
#ifndef TEST_DEF1
#error "undefined: TEST_DEF1"
#endif
#ifndef TEST_DEF2
#error "undefined: TEST_DEF2"
#endif
}
MexTest.h:
#ifndef MEXTEST_H_
#define MEXTEST_H_
void TestFnc(double *p_u, double *p_y);
#endif
legacy_code tool
specs = legacy_code('initialize');
specs.HeaderFiles = {'MexTest.h'};
specs.SourceFiles = {'MexTest.c'};
specs.SFunctionName = 'Test_SFunc_gen';
specs.OutputFcnSpec = 'void TestFnc(double u1[1], double y1[1])';
%% Compile C-MEX-s-function
legacy_code('sfcn_cmex_generate', specs);
legacy_code('generate_for_sim',specs);
legacy_code('compile', specs, {'-DTEST_DEF1', '-DTEST_DEF2'});
Mex Build Errors:
### Start Compiling Test_SFunc_gen
mex('-IC:\Users\xxxx\Documents\', '-c', '-outdir', 'C:\Users\xxxx\AppData\Local\Temp\tp05e00c12_2732_4dab_a0f8_f30bd05992f8', 'C:\Users\xxxx\Documents\MexTest.c')
Building with 'MinGW64 Compiler (C)'.
Error using mex
C:\Users\xxxx\Documents\MexTest.c: In function 'TestFnc':
C:\Users\xxxx\Documents\MexTest.c:8:10: error: #error "undefined: TEST_DEF1"
#error "undefined: TEST_DEF1"
C:\Users\xxxx\Documents\MexTest.c:12:10: error: #error "undefined: TEST_DEF2"
#error "undefined: TEST_DEF2"
How could I use the -D option correctly for my case?
(Matlab version 2021a)
I'll develop new (external) functions for DB2. My first test:
db2crypt.h
#ifndef DB2CRYPT_H
#define DB2CRYPT_H
#include <string.h>
#include <stdlib.h>
char *encryptAes(const char *source, const char *key);
#endif /* DB2CRYPT_H */
db2crypt.cpp
#include "db2crypt.h"
#include <string>
char *encryptAes(const char *source, const char *key) {
std::string test("abc");
return (char *)test.c_str();
}
is compiled without an error.
g++ -fPIC -c db2crypt.cpp -std=c++14
g++ -shared -o db2crypt db2crypt.o -L$DB2PATH -ldb2
I also copied the new file into $DB2PATH/function and made a softlink in $DB2PATH/function/unfenced.
Then I created the function with
create function aes(VARCHAR(4096), VARCHAR(4096))
SPECIFIC encryptAes
RETURNS VARCHAR(4069)
NOT FENCED
DETERMINISTIC
NO SQL
NO EXTERNAL ACTION
LANGUAGE C
RETURNS NULL ON NULL
INPUT PARAMETER STYLE SQL
EXTERNAL NAME "db2crypt!encryptAes"
which was also ok.
But when I do select db2inst1.aes('a', 'b') from SYSIBM.SYSDUMMY1
I get the error
SQL0444N Die Routine "DB2INST1.AES" (spezifischer Name "ENCRYPTAES") ist
durch Code in Bibliothek oder Pfad ".../sqllib/function/db2crypt", Funktion
"encryptAes" implementiert, auf die kein Zugriff möglich ist. Ursachencode:
"6". SQLSTATE=42724
(sorry, I don't know how to change the error output into english)
What I made wrong?
Ok, I got the answer.
Thank you at #mao, you did help me. But I also needed some other help. If someone searches for an answer:
First you have to compile with some important parameters:
g++ -m64 -fPIC -c <yourfile>.cpp -std=c++14 -I/opt/ibm/db2/V11.1/include/ -D_REENTRANT
g++ -m64 -shared -o <yourfile> <yourfile>.o -L$DB2PATH -ldb2 -Wl,-rpath,$DB2PATH/$LIB -lpthread
Second: The function declaration, you also have to add parameters for null values AND the return value can't be a function return, it has to be a parameter. Also you have to use the types which are defined in sqludf.h:
void SQL_API_FN encryptAes(SQLUDF_CHAR *source,
SQLUDF_CHAR *key,
SQLUDF_CHAR out[4096],
SQLUDF_SMALLINT *sourcenull,
SQLUDF_SMALLINT *keynull,
SQLUDF_SMALLINT *outnull,
SQLUDF_TRAIL_ARGS) {
...
}
Also, when you do C++ instead of C, you have to tell the script that it has to handle the function as C:
#ifdef __cplusplus
extern "C"
#endif
void SQL_API_FN ...
I have a quite simple Swig Module for Demo purposes but can't get the wrapper/stub to get compiled.
Swigtest.h:
#pragma once
class Swigtest {
public:
Swigtest() {};
int func1(int param1);
};
Swigtest.cpp
#include "Swigtest.h"
int Swigtest::func1(int param1)
{
return param1 + 1;
}
Swigtest.i
%module Swigtest
%{
#include "Swigtest.h"
%}
%include "Swigtest.h"
The wrapper ist generated with swig.exe -c++ -perl5 Swigtest.i and then the compilation of the wrapper Swigtest_wrap.cxx fails with the following first error:
[path_to_perl_lib]\lib\core\win32.h(371): error C2061: syntax error: identifier 'STRLEN'
I'm using VisualStudio 2015 Toolset (acutally running on VS17) with Target Platform Version 8.1 and Swigwin 3.0.12.
Thank's for your help!
I'm trying to define a class with multiple constructors methods, some of which take keyword arguments. Everything works as expected/intended until the constructor is passed a bad parameter list, in which case the interpreter dies instead of throwing an exception. Here's a minimal example:
#include <boost/python.hpp>
#include <string>
class Crash {
public:
Crash(std::string) { }
Crash(int, int) { }
};
BOOST_PYTHON_MODULE(mymodule) {
using namespace boost::python;
class_<Crash>("Crash", init<std::string>())
.def(init<int, int>((arg("i") = 3)))
;
}
Output:
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win 32
Type "help", "copyright", "credits" or "license" for more information.
>>> import mymodule as mm
>>> mm.Crash("asdf")
<mymodule.Crash object at 0x00D9FB70>
>>> mm.Crash(3)
<mymodule.Crash object at 0x00D9FE10>
>>> mm.Crash(4, i=5)
<mymodule.Crash object at 0x00D9FB70>
>>> mm.Crash(i=3) # kills the interpreter
Putting in an invalid keyword, e.g., Crash(blah=4), also kills the interpreter.
Is this a Boost.Python bug, or am I doing something wrong?
I'm using Boost 1.51 / Python 2.7.3 / MSVC 9.0.
I've written simple program.
Here a code:
#include <iostream>
#include <stdio.h>
#include <D:\Program Files\PostgreSQL\8.4\include\libpq-fe.h>
#include <string>
using namespace std;
int main()
{
PGconn *conn;
PGresult *res;
int rec_count;
int row;
int col;
cout << "ble ble: " << 8 << endl;
conn = PQconnectdb("dbname=db_pm host=localhost user=postgres password=postgres");
if (PQstatus(conn) == CONNECTION_BAD) {
puts("We were unable to connect to the database");
exit(0);
}
}
I'm trying to connect with PostgreSQL.
I compile this code with following command:
gcc -I/"d:\Program Files\PostgreSQL\" -L/"d:\Program Files\PostgreSQL\8.4\lib\" -lpq -o firstcpp.o firstcpp.cpp
This command is from following site:
http://www.mkyong.com/database/how-to-building-postgresql-libpq-programs/
And when I compile it I get following error:
/cygnus/cygwin-b20/H-i586-cygwin32/i586-cygwin32/bin/ld: cannot open -lpq: No such file or directory
collect2: ld returned 1 exit status
Does anyone help me?
Difek
You can try using forward slashes instead of backward slashes. And I have no idea about the first forward slash. Isn't it meant to be inside the quotes ? Eg -I"/d:/Program Files/PostgreSQL/"
Anyway, if you are using the gcc from cygwin, you could also try
-I"/cygdrive/d/Program Files/PostgreSQL"
And I'd do the same with that include (libpq-fe) - though apparently that is working, the error is in the linker.