I'm trying to throw exception which is defined inside class in extension module created with python C api.
Here is what I want in python C api, but written in python:
class Graph:
class TooManyVerticesError( Exception ): pass
def addVertex( self ):
if self.__order == 16:
raise Graph.TooManyVerticesError( "too many vertices" )
for v in range( self.__order ):
self.__matrix[v] += [False]
self.__order += 1
self.__matrix += [ [False] * self.__order ]
Here is what I have now written with python C api:
#define ERROR return NULL;
PyObject *TooManyVerticesError;
typedef struct {
PyObject_HEAD
size_t __order; /* the maximum number of elements in q_elements */
std::vector<std::vector<int>> AdjacencyList;
} ListaSasiedztwa;
static
PyObject* addVertex(ListaSasiedztwa* self, PyObject* args)
{
int u, v;
// Process arguments
PyArg_ParseTuple(args, "ii",
&u,
&v);
if (self->__order == 16)
{
PyErr_SetString(TooManyVerticesError, "too many vertices");
ERROR
}
std::vector<int> vertexList;
self->AdjacencyList.push_back(vertexList);
return NULL;
}
PyMODINIT_FUNC PyInit_simple_graphs(void)
{
if (PyType_Ready(&ListaSasiedztwaType) < 0) return NULL;
PyObject* m = PyModule_Create(&cSimpleGraphsModule);
if (m == NULL) return NULL;
TooManyVerticesError = PyErr_NewException("simple_graphs.TooManyVerticesError", NULL, NULL);
PyDict_SetItemString(ListaSasiedztwaType.tp_dict, "TooManyVerticesError", TooManyVerticesError);
Py_INCREF(&ListaSasiedztwaType);
PyModule_AddObject(m, "ListaSasiedztwa",
(PyObject *)&ListaSasiedztwaType);
return m;
}
Everything builds correctly, I can create object of type ListaSasiedztwa. But when exception should be thrown I have Exception of type SystemError with message:
class 'simple_graphs.ListaSasiedztwa' returned a result with an error set.
Should I add this Exception as structure member somehow?
I don't know if ListaSasiedztwaType is relevant in this problem so I didn't add it yet.
I think you're actually hitting the return NULL; at the end of the function which you reach in the "non-error" case. This NULL indicates to Python that their should be an exception set, but since there isn't one you get the general SystemError from Python..
I suspect you're trying to return the Python None object - use the macro Py_RETURN_NONE instead.
It occured that addVertex was called from another method which didn't pass return value which had to be NULL.
Related
I am trying to implement a TSortedMap with my custom struct as the key. I have overloaded the operators for the struct. However, when I try to compile I get this error at the line of code where I am adding an element to the TSortedMap:
error C2678: binary '<': no operator found which takes a left-hand operand of type 'const T'
(or there is no acceptable conversion)
My struct:
USTRUCT(BlueprintType)
struct FUtility
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere, meta=(ClampMin = "0.0", ClampMax = "1.0"))
float value = 0.0f;
UPROPERTY(BlueprintReadWrite, EditAnywhere, meta = (ClampMin = "0.0", ClampMax = "1.0"))
float weight = 1.0f;
FORCEINLINE bool operator== (const FUtility& other)
{
return this->value == other.value && this->weight == other.weight;
}
FORCEINLINE bool operator< (const FUtility& other)
{
return (this->value * this->weight) < (other.value * other.weight);
}
.....
friend uint32 GetTypeHash(const FUtility& other)
{
return GetTypeHash(other.value) + GetTypeHash(other.weight);
}
};
Not quite sure why it is not compiling since it is overloaded. Maybe it isn't overloaded correctly. Any help would be greatly appreciated.
Well, oddly enough I figured it out. It was really bugging me that all of the operator logic in the documentation took two parameters. It turns out I was just missing the friend keyword. From there I was able to add the second parameter and it compiled nicely.
Example:
friend bool operator< (const FUtility& a, const FUtility& b)
{
return (a.value * a.weight) < (b.value * b.weight);
}
I recently started to learn Groovy and found not a natural behavior.
class BasicRouter {
int method_(first){
return 1;
}
int method_(int first){
return 2;
}
int method_(short second){
return 3;
}
int method_(Integer first){
return 4;
}
}
br = new BasicRouter()
int x = 1
assert br.method_(x) == 4
assert br.method_((int)29) == 2
Why in the first case we are passing a variable of type int, we get 4 and not 2?
I expect that method int method_(int) will be called.
Thanks.
The answer is here - http://docs.groovy-lang.org/latest/html/documentation/core-differences-java.html#_primitives_and_wrappers
Groovy uses objects for everything
This changes if you use CompileStatic
#groovy.transform.CompileStatic
def fInt(int x) {new BasicRouter().method_(x)}
assert fInt(1) == 2
In Groovy, I can overload operator '+' plus as follow:
class MutableInt {
int val
MutableInt(int val) { this.val = val }
MutableInt plus(int val) {
return new MutableInt(this.val += val)
}
}
The above class works fine for the following test cases:
def m1 = new MutableInt(1);
assert (m1 + 1).val == 2;
However, if I need to use it together with Map like this and compile it with static
#groovy.transform.CompileStatic
void compileItWithStatic() {
Map<Long, MutableInt> mutMap = [:].withDefault{ new MutableInt(0) }
assert (mutMap[1L] += 20).val == 20;
}
compileItWithStatic()
I got the following error:
*Script1.groovy: 17: [Static type checking] -
Cannot call <K,V> java.util.Map <java.lang.Long, MutableInt>#putAt(java.lang.Long, MutableInt) with arguments [long, int]*
How can I override the '+=' operator and compile it with static without error?
EDIT:
If I am doing like this without compile static it works fine:
def m1 = new MutableInt(1);
assert (m1 += 1).val == 2 // <----- caution: '+=' not '+' as in previous case
However, if it was inside the method like this:
#groovy.transform.CompileStatic
void compileItWithStatic_2() {
def m1 = new MutableInt(1);
assert (m1 += 1).val == 2
}
The error will be:
Script1.groovy: -1: Access to java.lang.Object#val is forbidden # line -1, column -1.
1 error
P.S. It won't work with static compilation not with dynamic compilation.
The assignment part is throwing the error. A simple + works:
class MutableInt {
int val
MutableInt(int val) { this.val = val }
MutableInt plus(int val) {
return new MutableInt(this.val += val)
}
}
def m1 = new MutableInt(1);
assert (m1 + 1).val == 2;
#groovy.transform.CompileStatic
def compileItWithStatic() {
Map<Long, MutableInt> mutMap = [:].withDefault{ new MutableInt(0) }
mutMap[1L] + 20
mutMap
}
assert compileItWithStatic()[1L].val == 20
Groovy is parsing mutMap[1L] += 20 as mutMap.putAt(1L, 20). This looks like a bug to me. This works: mutMap[1L] = mutMap[1L] + 20, albeit more verbose.
Edit: the second error seems related to the result of the expression (m1 + 1) being parsed as Object. This should work:
#groovy.transform.CompileStatic
void compileItWithStatic_2() {
def m1 = new MutableInt(1) + 1;
assert m1.val == 2
}
There is a groovy script that has a function defined and used in multiple threads.
I found that time to time it mixes some variable values with other threads.
The problem appears when developer forgot to declare variable like this:
def f ( x ) {
y = "" + x
println y
}
The problem disappears when developer declares variable
def f ( x ) {
def y = "" + x
println y
}
In classes there is no way to use undefined variables.
The reason is that in the scripts the undefined variable acts as an instance variable of the script-class. Actually this is a binding for external variables that could be passed into the script.
Here is a part of script that demonstrates the problem of using undefined variables in several threads.
void f(String x){
y=""+x; //if you put def at this line it'll work fine
Thread.sleep(333);
//usually developers expected that `y` is a local variable,
//but without declaration it belongs to script-class
if( !y.equals(x) ) println("failure: x=$x y=$y");
}
//thead 1 start
Thread.start{
for(int i=0;i<20;i++){
f( i.toString() )
Thread.sleep(100);
}
}
//thead 2 start
Thread.start{
for(int i=0;i<20;i++){
f( i.toString() )
Thread.sleep(150);
}
}
//main thread sleep.
Thread.sleep(2000);
println("done");
this code will print out failures when x not equals y (literally)
Write a compiler configuration using a scriptBaseClass to disallow undeclared variables and the usage of the script's own binding.
This is the base script (my DefBase.groovy file):
abstract class NoUndefShallPass extends Script {
void setProperty(String name, val) {
// seems like groovy itself set 'args' in the binding, probably from CL
assert name == 'args',
"Error in '$name'; variables should be declared using 'def'"
}
}
def configuration = new org.codehaus.groovy.control.CompilerConfiguration()
configuration.setScriptBaseClass(NoUndefShallPass.class.name)
def shell = new GroovyShell(this.class.classLoader, new Binding(), configuration)
shell.evaluate new File('/tmp/Defing.groovy')
And the script. It will thrown an AssertionError if the setProperty tries to use the binding:
void f(String x){
y=""+x; //if you put def at this line it'll work fine
Thread.sleep(333);
if( !y.equals(x) ) println("failure: x=$x y=$y");
}
def t1 = Thread.start{
20.times { i ->
f( i.toString() )
Thread.sleep(100);
}
}
def t2 = Thread.start{
20.times { i ->
f( i.toString() )
Thread.sleep(150);
}
}
Thread.sleep(2000);
t1.join()
t2.join()
println("done");
it's poorly described here as "the binding"
http://groovy.codehaus.org/Scoping+and+the+Semantics+of+%22def%22
In an embedded python scenario we are using PyArg_ParseTupleAndKeywords to receive data from Python (version >=3 .x) and use it in a C++ application.
At the moment we have a similar setup:
PyObject* whatever(PyObject *self, PyObject *args, PyObject *keywds) {
....
static char* kwlist[] = { "foo", "bar", NULL };
...
if(!PyArg_ParseTupleAndKeywords(args, keywds, ..., kwlist, ...))
{
...bail out
however, if we pass more parameters than the two expected (e.g. issuing a python call like whatever(foo="a", bar="b", baz="c")) the whole thing crashes (not really, it returns an error, but that's beyond the scope here).
We would like to avoid such scenarios; it would be great if we could parse only the parameters in the kwlist and ignore everthing else. What's the best way to do it?
One solution we were thinking about was to convert kwlist into a dict, then manipulate it with PyDict_Merge or the like.
In the end we solved it like below:
(I'm answering my own question since nobody answered, and I think it might be valuable to somebody else in the future).
PyObject* whatever(PyObject *self, PyObject *args, PyObject *incoming_keywds)
{
static char* kwlist[] = { "foo", "bar", NULL };
PyObject* keywds = PyDict_New();
/**
* The following routine returns a subset of the incoming dictionary 'incoming_keywds'
* containing only the keys allowed in the list 'kwlist'
*/
for ( int i = 0 ; kwlist[i] != NULL ; i++ )
{
char* key = kwlist[i];
PyObject *single_key = Py_BuildValue("s", key);
if ( PyDict_Contains(incoming_keywds, single_key) )
{
// not checking for NULL as GetItem return value since
// we already checked above if the dict contains key 'single_key'
if ( PyDict_SetItem(keywds, single_key, PyDict_GetItem(incoming_keywds, single_key)) < 0 )
{
/* error */
}
}
Py_DECREF(single_key);
}
/** end */