C#中的IronPython和Nodebox

4 投票
1 回答
931 浏览
提问于 2025-04-16 09:18

我的计划:

我想设置我的C#项目,让它能和Nodebox通信,以调用一个特定的函数,这个函数可以填充一个图形并在新窗口中绘制出来。

目前情况:[已修复...见更新2]

我已经包含了所有需要的Python模块,但我仍然遇到一个问题:

找不到库 'GL'

看起来pyglet模块需要引用GL/gl.h,但由于IronPython的行为,它找不到这个文件。

需求:

这个项目需要尽量保持小,不想安装新的包。因此,我把所有模块都复制到了项目文件夹里,希望能保持这种方式。

我的问题:

有没有什么方法可以解决我的问题,或者修复库文件夹不匹配的情况?我看过一些关于Tao-OpenglOpenTK的文章,但找不到好的解决方案。

更新1:

我更新了我的源代码,增加了一个小的pyglet窗口渲染示例。问题出在pyglet和引用的C对象上。我该如何在我的C#项目中包含它们以便调用呢?到现在为止我还没有头绪...现在正在尝试一些方法,稍后会更新你们。

示例代码 C#:

ScriptRuntimeSetup setup = Python.CreateRuntimeSetup(null);
ScriptRuntime runtime = new ScriptRuntime(setup);
ScriptEngine engine = Python.GetEngine(runtime);

ScriptSource source = engine.CreateScriptSourceFromFile("test.py");
ScriptScope scope = engine.CreateScope();
source.Execute(scope);

示例代码 Python (test.py):

from nodebox.graphics import *
from nodebox.graphics.physics import Vector, Boid, Flock, Obstacle

flock = Flock(50, x=-50, y=-50, width=700, height=400)
flock.sight(80)

def draw(canvas):
    canvas.clear()
    flock.update(separation=0.4, cohesion=0.6, alignment=0.1, teleport=True)
    for boid in flock:
        push()
        translate(boid.x, boid.y)
        scale(0.5 + boid.depth)
        rotate(boid.heading)
        arrow(0, 0, 15)
        pop()

canvas.size = 600, 300

def main(canvas):
    canvas.run(draw)

更新2:

在第139行 [pyglet/lib.py] 发现 sys.platform 不是 win32... 这就是错误所在。我通过使用以下代码修复了它:

from pyglet.gl.lib_wgl import link_GL, link_GLU, link_WGL

现在出现了以下错误:

'module' object has no attribute '_getframe'

修复这个问题真是麻烦。会继续更新结果...

更新3:

通过在C#代码的第一行后面添加以下代码修复了问题:

setup.Options["Frames"] = true;

当前问题:

没有名为 unicodedata 的模块,但在Python26/DLLs中只有一个*.pyd文件。那么...我现在该怎么实现呢?!

更新4:

通过浏览这个链接:链接文本,并将unicodedata.py'.pyd'添加到C#项目文件夹中,解决了问题。

当前问题:

'libGL.so 找不到'...伙计们,我快要放弃在C#中使用nodebox了...待续

更新5:

我放弃了 :/ 解决方法是:C#通过XML和文件监视器与Nodebox通信。这不是最优的,但问题解决了。

1 个回答

0

-X:Frames 这个选项可以让你在运行时使用框架(frames),不过这样会稍微影响代码的运行速度,因为它需要一直访问 Python 的框架。

如果你想在托管时启用框架,只需要这样做:

ScriptRuntimeSetup setup = Python.CreateRuntimeSetup(new Dictionary<string, object>() {
    { "Frames", true }
});

这样就可以替代你现在传入的 null。这个操作其实是在为选项字典创建一个新的字典,并把“Frames”设置为 true。你也可以在这里设置其他选项,通常来说,-X:Name 这个选项在这里和命令行中的用法是一样的。

撰写回答