0

我有以下两个文件:

桥接程序:

package cube

// #cgo LDFLAGS: -lGL -lGLEW -lglfw
// #include <GLFW/glfw3.h>
// int init(GLFWwindow**);
// void render(GLFWwindow*);
import "C"

import (
    "fmt"
    "time"
)

func Init() {
    var window *_Ctype_GLFWwindow
    windowWat := (*[0]byte)(window)
    fmt.Printf("Calling init\n")
    if C.init(&windowWat) != 1 {
        return
    }
    window = (*_Ctype_GLFWwindow)(windowWat)

    //t := time.Tick(time.Second) // Doesn't work
    t := time.After(time.Second) // Works

    <-t
    fmt.Println("Rendering")
    C.render((*[0]byte)(window))

    select {}
}

立方体.c:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

#define INIT_WINDOW_W (800)
#define INIT_WINDOW_H (800)

void render(GLFWwindow* window) {
    glClearColor(135.0f / 255.0f, 206.0f / 255.0f, 250.f / 254.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glfwSwapBuffers(window);
}

static void glfw_error(int errno, const char* description) {
    fprintf(stderr, "GLFW [%d] %s\n", errno, description);
    exit(1);
}

int init(GLFWwindow** window) {
    GLenum glewErr;

    glfwSetErrorCallback(glfw_error);
    if (!glfwInit()) {
        return 0;
    }

    *window = glfwCreateWindow(
        INIT_WINDOW_H,
        INIT_WINDOW_W,
        "wat",
        NULL,
        NULL
    );
    if (*window == NULL) {
        glfwTerminate();
        return 0;
    }

    glfwMakeContextCurrent(*window);

    glewErr = glewInit();
    if (glewErr != GLEW_OK) {
        fprintf(stderr, "glewInit failed: %s\n", glewGetErrorString(glewErr));
        return 0;
    }

    if (!GL_VERSION_2_0) {
        fprintf(stderr, "Don't have OpenGL >= 2.0\n");
        return 0;
    }

    return 1;
}

以及一个调用的 main.go 文件,仅此cube.Init()而已。

我的问题在于调用C.render. 如果我这样做time.After,它可以正常工作并按预期显示一个蓝色窗口。如果我做 a time.Tick,它很少会显示那个蓝色窗口,但要么显示黑色窗口,要么显示段错误。这个测试用例很大程度上是从我的实际代码中总结出来的。

我有一种感觉,go 的调度程序以某种方式把事情搞砸了,但我想不出如何(或如何测试/修复它)。我很好奇是否有人有任何想法是什么导致了这种情况,或者可以想出任何进一步调查的方法。

其他可能重要的信息:

  • Arch linux,3.14.4-1-ARCH.x86_64
  • GLFW 3.0.4-1
  • GLEW 1.10.0-2
  • 英伟达 GeForce GTX 570M
  • 英伟达驱动程序 337.12-1
  • go1.2 linux/amd64

编辑:

这是段错误消息:

SIGSEGV: segmentation violation
PC=0x7fda7d6a2e29
signal arrived during cgo execution

runtime.cgocall(0x401260, 0x7fda7d6f0e58)
        /opt/go/src/pkg/runtime/cgocall.c:149 +0x11b fp=0x7fda7d6f0e40
game/cube._Cfunc_render(0x24e13b0)
        game/cube/_obj/_cgo_defun.c:62 +0x31 fp=0x7fda7d6f0e58
game/cube.Init()
        /tmp/wat/cube/bridge.go:28 +0x156 fp=0x7fda7d6f0ee0
main.main()
        /tmp/wat/main.go:10 +0xac fp=0x7fda7d6f0f48
runtime.main()
        /opt/go/src/pkg/runtime/proc.c:220 +0x11f fp=0x7fda7d6f0fa0
runtime.goexit()
        /opt/go/src/pkg/runtime/proc.c:1394 fp=0x7fda7d6f0fa8

goroutine 3 [syscall]:
runtime.goexit()
        /opt/go/src/pkg/runtime/proc.c:1394

rax     0x0
rbx     0x24e13b0
rcx     0x7fda7d6f0e58
rdx     0x7fda7d6f0df0
rdi     0x24e13b0
rsi     0xc210001900
rbp     0xc21002a000
rsp     0x7fda76506dc8
r8      0xc210001120
r9      0x7fda7d6f0df0
r10     0x7fda76506ba0
r11     0x7fda7d6a2e20
r12     0x0
r13     0x7fda76507700
r14     0x0
r15     0x7fda76d07c80
rip     0x7fda7d6a2e29
rflags  0x10202
cs      0x33
fs      0x0
gs      0x0
exit status 2

它似乎在调用时出现段错误glClearColor

4

1 回答 1

2

将我的评论变成答案:

出于某种原因,OpenGL 通常要求所有东西都在同一个 OS 线程中运行。time.Tick 和 time.After 调用不同的运行时函数,其中一个可能导致不同的 opengl 调用在不同的线程中运行。默认情况下,Go 不保证 goroutine 在特定线程上运行。

要解决此问题,您需要使用runtime.LockOSThread。这将确保 goroutine 并且只有那个 goroutine 在当前线程上运行。

您可以在此处阅读有关该主题的更多信息:https ://groups.google.com/forum/#!topic/golang-nuts/5Pvv1Gr1eoo

于 2014-05-27T19:21:37.130 回答