Я пытаюсь создать расширение C для python, которое позволяет мне создавать окно с изображением, отображаемым с помощью OpenGL.Я видел код в C https://github.com/codeplea/opengl-tcltk и хотел реализовать его в расширении, но когда я импортировал его, он генерирует следующую ошибку:
>>> import hello
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError:
/home/isaac/opengl/build/lib.linux-x86_64-3.5/hello.cpython-35m-x86_64-linux-gnu.so: undefined symbol: glBlendFunc
Я создаю Cрасширения, так что мне нужна небольшая помощь.
Он не запустился до первого, но после некоторых модификаций, скомпилированных без проблем
$ python setup.py build
running build
running build_ext
building 'hello' extension
x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/home/isaac/myCode/python/venv_statistics/include -I/usr/include/python3.5m -c hello.c -o build/temp.linux-x86_64-3.5/hello.o -Wall -I/usr/include/tcl -ltcl -ltk -lGL
x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.5/hello.o -o build/lib.linux-x86_64-3.5/hello.cpython-35m-x86_64-linux-gnu.so
Я работаю на Linux Mint 18 Cinnamon 64-bit.
/ hello.c
#include <stdio.h>
#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <tcl.h>
#include <tk.h>
#include <GL/gl.h>
Display *__glDisplay__ = (Display *)NULL;
Window __glWindow__;
int SetRenderWindow(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
Tk_Window __glTkwin__;
XVisualInfo *__glVisinfo__ = (XVisualInfo *)NULL;
int dummy;
int attribs[] =
{GLX_USE_GL, GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 0};
GLXContext __glGLXContext__ = (void *)NULL;
__glTkwin__ = Tk_NameToWindow(interp, Tcl_GetString (objv[1]), Tk_MainWindow(interp));
if (__glTkwin__ == NULL) {
fprintf(stderr, "__glTkwin__ is NULL\n" );
exit(-1);
}
Tk_MakeWindowExist( __glTkwin__);
__glDisplay__ = Tk_Display(__glTkwin__);
if (__glDisplay__ == NULL) {
fprintf(stderr, "__glDisplay__ is NULL\n" );
exit(-1);
}
if (!glXQueryExtension(__glDisplay__, &dummy, &dummy)) {
fprintf(stderr, "require GLX Extesion\n" );
exit(-1);
}
__glWindow__ = Tk_WindowId( __glTkwin__ );
__glVisinfo__ =
glXChooseVisual( __glDisplay__, DefaultScreen(__glDisplay__), attribs);
if (__glVisinfo__ == NULL) {
fprintf(stderr, "__glVisinfo__ is NULL\n" );
exit(-1);
}
__glGLXContext__ =
glXCreateContext(__glDisplay__, __glVisinfo__, 0, GL_TRUE);
if (__glGLXContext__ == NULL) {
fprintf(stderr, "__glGLXContext__ is NULL\n" );
exit(-1);
}
glXMakeCurrent( __glDisplay__, __glWindow__, __glGLXContext__ );
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(1.0, 1.0, 1.0, 0.0f);
glClearDepth(1.0);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glMatrixMode(GL_PROJECTION);
return TCL_OK;
}
int Resize(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
int w, h;
Tcl_GetIntFromObj(interp, objv[1], &w);
Tcl_GetIntFromObj(interp, objv[2], &h);
float dx = (float)w/h;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2*dx, 2*dx, -2, 2, -2, 2);
return TCL_OK;
}
void Loop(ClientData cd)
{
Tcl_Interp *interp = (Tcl_Interp*)cd;
Tcl_CreateTimerHandler(25, Loop, interp);
static float rot = 0;
rot += .5;
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(rot, 1.0f, 1.0f, 0.5f);
glBegin(GL_QUADS);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glColor3f(1.0f, 0.5f, 0.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(1.0f, 0.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glEnd();
glFlush();
glXSwapBuffers(__glDisplay__, __glWindow__);
}
void Cleanup(ClientData cd)
{
printf("Done\n");
}
int Init(Tcl_Interp *interp)
{
Tcl_Init(interp);
Tk_Init(interp);
Tcl_CreateObjCommand(interp, "SetRenderWindow", SetRenderWindow, 0, 0);
Tcl_CreateObjCommand(interp, "Resize", Resize, 0, 0);
Tcl_CreateTimerHandler(10, Loop, interp);
Tcl_CreateExitHandler(Cleanup, 0);
return TCL_OK;
}
static PyObject* init_windows(PyObject *self, PyObject *args) {
printf("Init windows!\n");
char *p[] = {"OpenGL Test", "gui.tcl"};
Tk_Main(2, p, Init);
printf("End windows!\n");
Py_RETURN_NONE;
}
static PyMethodDef hello_methods[] = {
{"init_windows", init_windows, METH_NOARGS, ""},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef hello_definition = {
PyModuleDef_HEAD_INIT, "hello", "", -1, hello_methods
};
PyMODINIT_FUNC PyInit_hello(void) {
Py_Initialize();
return PyModule_Create(&hello_definition);
}
/ setup.py
#!/usr/bin/env python3
# encoding: utf-8
from distutils.core import setup, Extension
setup(name='hello',
version='0.1.0',
description='Open a window using tkinter and opengl.',
ext_modules=[
Extension('hello', sources = ['hello.c'],
extra_compile_args = ["-Wall","-I/usr/include/tcl","-ltcl","-ltk","-lGL"])
])
/ gui.tcl
package require Tk
update idletasks
proc bgerror {message} {
tk_messageBox -message "Background error: $message\n\n$::errorInfo"
}
set display [frame .opengl -width 300 -height 200 -background white -takefocus 1]
pack $display -fill both -expand 1
SetRenderWindow $display [winfo id $display]
bind $display <Configure> {Resize %w %h}
Я знаю, что возможносделать это с помощью PyOpenGl, но немного рендерить немного, поэтому я предпочитаю использовать чистый C.
Результат должен выглядеть примерно так: