here read around: nortikin/sverchok#2345 (comment)
Last active
June 9, 2020 15:22
-
-
Save zeffii/2c90a56c64d241ee03e3477ffb00bed0 to your computer and use it in GitHub Desktop.
how to use cffi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# BEGIN GPL LICENSE BLOCK ##### | |
# | |
# This program is free software; you can redistribute it and/or | |
# modify it under the terms of the GNU General Public License | |
# as published by the Free Software Foundation; either version 2 | |
# of the License, or (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program; if not, write to the Free Software Foundation, | |
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
# | |
# END GPL LICENSE BLOCK ##### | |
import bpy | |
from bpy.props import StringProperty, IntVectorProperty, FloatVectorProperty, BoolProperty | |
from sverchok.utils.snlite_importhelper import ( | |
set_autocolor | |
) | |
from sverchok.node_tree import SverchCustomTreeNode | |
from sverchok.data_structure import updateNode | |
FAIL_COLOR = (0.8, 0.1, 0.1) | |
READY_COLOR = (0, 0.8, 0.95) | |
class SvCFFINodeCallBack(bpy.types.Operator): | |
bl_idname = "node.cffi_ui_callback" | |
bl_label = "CFFI Node callback" | |
fn_name: bpy.props.StringProperty(default='') | |
def execute(self, context): | |
getattr(context.node, self.fn_name)() | |
return {'FINISHED'} | |
class SvCFFINode(bpy.types.Node, SverchCustomTreeNode): | |
''' cffi CFFI Node /// a cffi Node ''' | |
bl_idname = 'SvCFFINode' | |
bl_label = 'CFFI Node' | |
bl_icon = 'SCRIPTPLUGINS' | |
script_name: StringProperty() | |
script_str: StringProperty() | |
n_id: StringProperty(default='') | |
def draw_label(self): | |
if self.script_name: | |
return 'CFFI: ' + self.script_name | |
else: | |
return self.bl_label | |
def sv_init(self, context): | |
self.use_custom_color = False | |
def clear_sockets(self): | |
self.inputs.clear() | |
self.outputs.clear() | |
def check_socket(self, dir, name, type): | |
if dir == "in": | |
if name not in self.inputs: | |
if type == "v": | |
self.inputs.new("SvVerticesSocket", name) | |
elif type == "m": | |
self.inputs.new("SvMatrixSocket", name) | |
elif type == "s": | |
self.inputs.new("SvStringsSocket", name) | |
elif dir == "out": | |
if name not in self.outputs: | |
if type == "v": | |
self.outputs.new("SvVerticesSocket", name) | |
elif type == "m": | |
self.outputs.new("SvMatrixSocket", name) | |
elif type == "s": | |
self.outputs.new("SvStringsSocket", name) | |
def make_sockets(self, mdl): | |
sock_str = "" | |
if hasattr(mdl, "sockets"): | |
sock_str = mdl.sockets | |
if sock_str != "": | |
for line in sock_str.split('\n'): | |
L = line.strip() | |
if L.startswith("'''"): | |
quotes += 1 | |
if quotes == 2: | |
break | |
elif L.startswith('in ') or L.startswith('out '): | |
split = L.split(' ') | |
if len(split) != 3: | |
continue | |
socket_dir = split[0] | |
socket_name = split[1] | |
socket_type = split[2] | |
self.check_socket(socket_dir, socket_name, socket_type) | |
def load(self, name): | |
import imp | |
if name in bpy.data.texts: | |
self.script_str = bpy.data.texts[name].as_string() | |
mdl = imp.new_module(name) | |
#warning, dangerous ! | |
exec(self.script_str, mdl.__dict__) | |
return mdl | |
else: | |
return None | |
def compile(self, mdl): | |
import cffi, os | |
py, build, srcs, incs, libs, lib_dirs, comp_arg, link_arg, lang = mdl.setup() | |
ffi = cffi.FFI() | |
ffi.cdef(mdl.cdef) | |
spaths = [] | |
for s in mdl.sources: | |
spaths.append(os.path.join(srcs, s)); | |
inc_dirs = [py, srcs] | |
inc_dirs.extend(incs) | |
#ffi.set_source(lib, code, sources=spaths, include_dirs=[py, src], language='c++') | |
#ffi.compile(verbose=True, tmpdir=build) | |
#verify automatically caches the binary, so it wont recompile over and over again | |
lib = ffi.verify(mdl.code, | |
tmpdir=build, | |
sources=spaths, | |
include_dirs=inc_dirs, | |
libraries=libs, | |
library_dirs=lib_dirs, | |
extra_compile_args=comp_arg, | |
extra_link_args=link_arg, | |
language=lang) # to be able to compile c++ too | |
return lib, ffi | |
def execute(self): | |
name = self.script_name | |
mdl = self.load(name) | |
if mdl is not None: | |
lib, ffi = self.compile(mdl) | |
#create sockets if not existing | |
self.make_sockets(mdl) | |
# execute glue / bind code from c script | |
# pass current node there, so we can access the socket variables | |
mdl.execute(lib, ffi, self) | |
#for experimental reason | |
#print("SHIT3") | |
return lib, ffi, mdl | |
def clear(self): | |
self.script_str = '' | |
self.script_name = '' | |
self.clear_sockets() | |
def process(self): | |
#try: | |
self.execute() | |
set_autocolor(self, True, READY_COLOR) | |
#except: | |
# set_autocolor(self, True, FAIL_COLOR) | |
def draw_buttons(self, context, layout): | |
sn_callback = 'node.cffi_ui_callback' | |
col = layout.column(align=True) | |
row = col.row() | |
if not self.script_str: | |
row.prop_search(self, 'script_name', bpy.data, 'texts', text='', icon='TEXT') | |
row.operator(sn_callback, text='', icon='PLUGIN').fn_name = 'process' | |
else: | |
row.operator(sn_callback, text='Reload').fn_name = 'process' | |
row.operator(sn_callback, text='Clear').fn_name = 'clear' | |
#self.custom_draw(context, layout) | |
classes = [ | |
SvCFFINodeCallBack, | |
SvCFFINode | |
] | |
def register(): | |
_ = [bpy.utils.register_class(name) for name in classes] | |
def unregister(): | |
_ = [bpy.utils.unregister_class(name) for name in classes] | |
try: | |
unregister() | |
except: | |
pass | |
register() | |
print("x") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sockets = """ | |
in points v | |
in edges s | |
out new_verts v | |
""" | |
cdef = """ | |
void intersectAll(float vertices[][3], int lines[][2], int count, float new_verts[][3], int num_new_verts[]); | |
""" | |
import bpy | |
code = bpy.data.texts['xall.c'].as_string() | |
sources = [ "mathlib.c" ] | |
def setup(): | |
import os, bpy | |
from pathlib import Path | |
root = Path(bpy.data.filepath).parent | |
py = Path(bpy.app.binary_path).parent / "2.80" / "python" / "include"; | |
build = Path(root) / "build"; | |
srcroot = Path(root) / "mathlib" | |
incroot = Path(root) / "mathlib" | |
srcs = str(srcroot) | |
incs = [str(incroot)] | |
libs = [] | |
lib_dirs = [] | |
comp = [] | |
link = [] | |
lang = 'c' | |
return str(py), str(build), srcs, incs, libs, lib_dirs, comp, link, lang | |
def execute(lib, ffi, node): | |
points = node.inputs["points"].sv_get(default=[[]])[0] | |
edges = node.inputs["edges"].sv_get(default=[[]])[0] | |
if not points and edges: | |
return | |
new_verts = xall(lib, ffi, points, edges) | |
if new_verts: | |
node.outputs["new_verts"].sv_set(new_verts) | |
def xall(lib, ffi, points, edges): | |
if not points and edges: | |
return [[]] | |
n = len(edges) | |
max_num = int(((n*n) - n) / 2) | |
new_verts = ffi.new("float[][3]", max_num) | |
cpoints = ffi.new("float[][3]", len(points)) | |
cedges = ffi.new("int[][2]", len(edges)) | |
num_new_verts = ffi.new('int[]', 1) | |
for i, p in enumerate(points): | |
cpoints[i] = p | |
for i, e in enumerate(edges): | |
cedges[i][0] = e[0] | |
cedges[i][1] = e[1] | |
count = len(edges) | |
lib.intersectAll(cpoints, cedges, count, new_verts, num_new_verts) | |
verts = [] | |
for i in range(max_num): | |
v = new_verts[i] | |
verts.append((v[0], v[1], v[2])) | |
return [verts] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// # xall.c | |
#include "mathlib.h" | |
void intersectAll(float vertices[][3], int lines[][2], int count, float new_verts[][3], int num_new_verts[]){ | |
int isect_result; | |
// int count = sizeof(lines) / sizeof(lines[0]); | |
printf("%d", count); | |
const float epsilon = 0.0001f; | |
float v1[3], v2[3], v3[3], v4[3], r_i1[3], r_i2[3]; | |
int intersections = 0; | |
for (int i = 0; i <= count; i++) { | |
for (int j = 0; j <= count; j++) { | |
// # skip identical indices and 1 half of 2d matrix by ignoring duplicate comparrisons | |
if (j <= i){ continue; } | |
if (lines[i][0] == lines[j][0] || lines[i][0] == lines[j][1]) { continue; } | |
if (lines[i][1] == lines[j][0] || lines[i][1] == lines[j][1]) { continue; } | |
copy_v3_v3(v1, vertices[lines[i][0]]); | |
copy_v3_v3(v2, vertices[lines[i][1]]); | |
copy_v3_v3(v3, vertices[lines[j][0]]); | |
copy_v3_v3(v4, vertices[lines[j][1]]); | |
isect_result = isect_line_line_epsilon_v3(v1, v2, v3, v4, r_i1, r_i2, epsilon); | |
if (isect_result == 0) { continue; } | |
else if (isect_result == 1) { copy_v3_v3(new_verts[intersections], r_i1); } | |
else if (isect_result == 2) { | |
copy_v3_v3(new_verts[intersections], r_i1); | |
copy_v3_v3(new_verts[intersections+1], r_i1); | |
} | |
intersections += isect_result; | |
} | |
} | |
// num_new_verts[0] = intersections; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment