Hi,
I am optimizing my code using cython. The big advantage of cython is that, in addition to compiled c++ code, I can use multiprocessing without significant overhead. However the problem with multiprocessing is that GIL is not allowed. Then no python objects and calls are allowed when I call nogil
.
My code (touch.pyx
) basically is:
@cython.boundscheck(False)
cdef float getClosestCollision(object py_physics_manager, str host_name, float max_distance, object origin, object tip):
"""
Check if objects are colliding with collision line and get the collision info of the
closest one.
"""
cdef:
LPoint3 cpp_origin, cpp_tip
BulletWorld* cpp_physics_manager
with nogil:
cpp_origin = <LPoint3>((<Dtool_PyInstDef*>origin)._ptr_to_object)
cpp_tip = <LPoint3>((<Dtool_PyInstDef*>tip)._ptr_to_object)
cpp_physics_manager = <BulletWorld*>((<Dtool_PyInstDef*>py_physics_manager)._ptr_to_object)
collisions = cpp_physics_manager.ray_test_all(cpp_origin, cpp_tip)
if collisions.get_num_hits() > 1:
# Get an list of collisions ordered by the closest ones
fractions = [hit.get_hit_fraction() for hit in collisions.get_hits() if
hit.get_node().get_name() != host_name]
if len(fractions) > 2:
return max(fractions) * max_distance
elif len(fractions) == 1:
return fractions[0] * max_distance
else:
return 0
else:
return 0
Now the “header file” (touch.pxd
) to help the link between my code and libpanda.lib
:
from libcpp.string cimport string
cdef extern from "py_panda.h":
cdef struct Dtool_PyInstDef:
void* _ptr_to_object
cdef extern from "lvecBase3_src.h":
cdef cppclass LVecBase3:
inline float get_x()
inline float get_y()
inline float get_z()
cdef extern from "lpoint3.h":
cdef cppclass LPoint3:
inline float get_x()
inline float get_y()
inline float get_z()
cdef extern from "lvector3.h":
cdef cppclass LVector3:
inline float get_x()
inline float get_y()
inline float get_z()
cdef extern from "nodePath.h":
cdef cppclass NodePath:
inline string get_name()
inline NodePath get_parent(Thread *current_thread)
LPoint3 get_relative_point(NodePath &other, LVecBase3 &point)
cdef extern from "bitMask.h":
cdef cppclass BitMask32
cdef extern from "bulletAllHitsRayResult.h":
cdef struct BulletRayHit:
NodePath *get_node()
LPoint3 get_hit_pos()
LVector3 get_hit_normal()
float get_hit_fraction()
cdef struct BulletAllHitsRayResult:
LPoint3 get_from_pos()
LPoint3 get_to_pos()
bint has_hits()
int get_num_hits()
BulletRayHit get_hit(int idx)
cdef extern from "bulletWorld.h":
cdef cppclass BulletWorld:
BulletAllHitsRayResult ray_test_all(LPoint3 &from_pos, LPoint3 &to_pos, CollideMask &mask) nogil except +
My Setup.py:
import sys
import os
import shutil
from pathlib import Path
from setuptools import setup, Extension
from Cython.Build import cythonize
include_dirs = []
library_dirs = []
if os.name == "nt":
include_dirs = [r"C:\Program Files\Python37\include",
r"C:\Panda3D-1.10.6-x64\include"]
library_dirs = [r"C:\Panda3D-1.10.6-x64\lib"]
elif os.name == "posix":
include_dirs = ["/Developer/Panda3D/include/"]
library_dirs = ["/Developer/Panda3D/python/libs/",
"/Developer/Panda3D/lib/"]
libraries = ["libp3framework",
"libpanda",
"libpandafx",
"libpandaexpress",
"libp3dtool",
"libp3dtoolconfig",
"libp3pystub",
"libp3direct"]
extensions = [
Extension("*",
sources=["*.pyx"],
include_dirs=include_dirs,
library_dirs=library_dirs,
libraries=libraries,
language="c++"),
Extension("*",
sources=["senses/*.pyx"],
include_dirs=include_dirs,
library_dirs=library_dirs,
libraries=libraries,
language="c++"),
Extension("*",
sources=["ui/*.pyx"],
include_dirs=include_dirs,
library_dirs=library_dirs,
libraries=libraries,
language="c++")]
setup(name="Avatar Studio",
package_dir={'avatar_studio': ''},
ext_modules=cythonize(extensions,
language_level=3))
Unfortunately this is not working:
senses\touch.cpp(4445): error C2065: 'LPoint3': undeclared identifier
senses\touch.cpp(4445): error C2146: syntax error: missing ';' before identifier '__pyx_v_cpp_origin'
senses\touch.cpp(4445): error C2065: '__pyx_v_cpp_origin': undeclared identifier
senses\touch.cpp(4446): error C2065: 'LPoint3': undeclared identifier
senses\touch.cpp(4446): error C2146: syntax error: missing ';' before identifier '__pyx_v_cpp_tip'
senses\touch.cpp(4446): error C2065: '__pyx_v_cpp_tip': undeclared identifier
senses\touch.cpp(4458): error C2065: '__pyx_v_cpp_origin': undeclared identifier
senses\touch.cpp(4458): error C2065: 'LPoint3': undeclared identifier
senses\touch.cpp(4467): error C2065: '__pyx_v_cpp_tip': undeclared identifier
senses\touch.cpp(4467): error C2065: 'LPoint3': undeclared identifier
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.27.29110\\bin\\HostX86\\x64\\cl.exe' failed with exit status 2
LPoint3
is not found by the linker. Could some help to point where is the error. Is the header lpoint3.h
correct?
The piece of the header (touch.pxd
) declaring LPoint3:
cdef extern from "lpoint3.h":
cdef cppclass LPoint3:
inline float get_x()
inline float get_y()
inline float get_z()