ImportError:在C扩展中实现Opengl代码和Tkinter时未定义的符号

2024-10-03 13:30:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试为python创建一个C扩展,它允许我使用OpenGL渲染的图像创建一个窗口。我在https://github.com/codeplea/opengl-tcltk的C中看到了代码,我想在扩展中实现它,但是当我导入它时,它会生成以下错误:

>>> 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肉桂64位。你知道吗

/你好,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);
}

你知道吗/设置.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"])
        ])

你知道吗/图形用户界面.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

结果应该是这样的


Tags: buildhelloincludelinuxtclnullx86tk