我有一个库,用于渲染来自网络的opengl和prinimaet流。
我在罂粟下写字,但计划在linux上使用
所以窗口是为目标c创建的 我开始在另一个线程中绘制接收和解码数据。
我在opengl的方法上崩溃了错误(EXT_BAD_ACCESS),即使我只在一个线程中使用它们。
我的代码 主要过剩:
int main(int argc, const char * argv[]){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
int win = glutGetWindow();
glutInitWindowSize(800, 600);
glutCreateWindow("OpenGL lesson 1");
client_init(1280, 720, win, "192.168.0.98", 8000, 2222);
return 0;
}
或目标c
- (id)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat*)format{
self = [super initWithFrame:frameRect];
if (self != nil) {
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFANoRecovery,
NSOpenGLPFAFullScreen,
NSOpenGLPFAScreenMask,
CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),
(NSOpenGLPixelFormatAttribute) 0
};
_pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
if (!_pixelFormat)
{
return nil;
}
//_pixelFormat = [format retain];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(_surfaceNeedsUpdate:)
name:NSViewGlobalFrameDidChangeNotification
object:self];
_openGLContext = [self openGLContext];
client_init(1280, 720, win, "192.168.0.98", 8000, 2222);
}
return self;
}
client_init代码
// pthread_create(&posixThreadID, NULL, (void*(*)(void*))ShowThread, dh_tmp);
pthread_create(&posixThreadID, NULL, (void*(*)(void*))ShowThread, NULL);
void* ShowThread(struct drawhandle * dh){
//glViewport(0, 0, dh->swidth, dh->sheight);//EXT_BAD_ACCESS
glViewport(0, 0, 1280, 720);//EXT_BAD_ACCESS
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//gluOrtho2D(0, dh->swidth, 0, dh->sheight);
gluOrtho2D(0, 1280, 0, 720);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
...
return 0;
}
我认为问题是什么?那个未创建的上下文opengl。
如何在macos / linux中创建它?
答案 0 :(得分:2)
此线程没有当前的OpenGL上下文。即使您之前在程序中创建了一个上下文(在您的代码段中不可见),它也不会是您启动的主题中的最新内容。
OpenGL上下文总是,没有例外,一次只有一个线程的“当前”。默认情况下,这是创建上下文的线程。任何调用OpenGL的线程都必须先“当前”。
您必须在此线程中创建上下文,或者调用glXMakeCurrent
(Unix / Linux)或aglMakeCurrent
(Mac)或wglMakeCurrent
(Windows)在ShowThread
内(在做与OpenGL相关的任何其他事情之前)。
(可能不是崩溃的原因,但是......看看datenwolf对崩溃可能原因的回答 - 尽管这是错误的)`
答案 1 :(得分:1)
OpenGL和多线程处理困难。它可以做到,但需要一些照顾。首先,OpenGL上下文一次只能在一个线程中处于活动状态。在某些系统上,如Windows扩展函数指针是每个上下文,因此对于不同线程中的不同上下文,您可能最终会得到不同的扩展函数指针,必须为其配置。
所以第一个问题是:你可能在这个线程上没有OpenGL上下文,但这不应该在调用非扩展函数时崩溃,它只会做什么。
如果它确实在您指定的行上崩溃,那么dh
指针无效是肯定的。这是唯一的解释。 C中的指针只是一些以特殊方式解释的数字。如果你传递指针 - 特别是如果用作回调或线程函数的参数 - 那么指向指针的对象必须不会无效,直到它确保无法再访问该指针为止。这意味着:您不能在堆栈上创建的内容上使用它,即在C自动存储中。
这会破坏:
void foo(void)
{
struct drawhandle dh_tmp;
pthread_create(&posixThreadID, NULL, (void*(*)(void*))ShowThread, &dh_tmp);
}
为什么呢?因为时间foo
返回对象dh_tmp
无效。但是&dh_tmp
(指向它的指针)只是一个数字,当dh_tmp
无效时,这个数字不会“神奇地”变为零。
您必须在堆上分配它才能使其正常工作。当然有问题,何时再次释放内存。