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

Python ImportError:未定义的符号-当我在C扩展中实现Opengl代码和Tkinter时,python,c,opengl,tkinter,Python,C,Opengl,Tkinter,我正在尝试为python创建一个C扩展,它允许我使用OpenGL渲染的图像创建一个窗口。我在C中看到了代码,我想在扩展中实现它,但当我导入它时,它会生成以下错误: >>> import hello Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: /home/isaac/opengl/build/lib.linux-x86_64-3

我正在尝试为python创建一个C扩展,它允许我使用OpenGL渲染的图像创建一个窗口。我在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
我正在使用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);
}
/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}
包需要Tk
更新idletasks
proc bgerror{message}{
tk_messageBox-消息“背景错误:$message\n\n$::errorInfo”
}
设置显示[frame.opengl-宽度300-高度200-背景白色-takefocus 1]
包装$display-填充两个-展开1
SetRenderWindow$display[winfo id$display]
绑定$display{Resize%w%h}
我知道用PyOpenGl可以做到这一点,但渲染某些东西有点慢,所以我更喜欢使用纯C

结果应该是这样的

#!/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"])
        ])
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}