[英]How to map video memory from python to c?
我一直在Python中玩弄一些简单的图形东西,但是为了提高性能,我想在C中做一些事情。
我知道如何来回传输 arrays 和东西。 这没什么大不了的。 But I thought it might be beneficial if I could just create a windows with a canvas, pass a pointer to the video memory (of course not the physical video memory) and then let Python take care of just putting that memory to the screen, while rest 在 C 中完成。 可能是异步的,但我不知道这是否重要。
这可能吗,这有意义吗? 还是我走错了路?
到目前为止我的努力:
# graphics.py
import ctypes
import pygame
screen = pygame.display.set_mode((300,200))
f = ctypes.CDLL('/path/to/engine.so')
f.loop(screen._pixels_address)
和
// engine.c
#include <stdint.h>
void loop(void *mem) {
while(1) {
uint8_t *p = (uint8_t*) mem;
// Was hoping this would make some pixels change
for(int i=0; i<20000; i++)
*p=127;
}
}
这没有用,最终导致崩溃。 我并不感到惊讶,但是,这就是我到目前为止所得到的。
并非绝对必须使用 Python。 但我确实想使用 C。 而且我也知道,在大多数情况下,我的方法并不是最好的方法,但我确实喜欢在 C 中编码并做一些老派的事情。
本质上,您希望与 Python 应用程序共享一个缓冲区。 有一个缓冲区协议就是为了这个目的而存在的。 本质上,您共享一个具有buf
和len
字段的Py_buffer
object。 (我没有通读全文,但您可以了解更多信息。)
事实证明, Surface.get_buffer()
已经返回了这样一个缓冲区 object。 换句话说,您可以直接将其传递给您的外部 function:
import pygame
background_colour = (255,255,255) # For the background color of your window
(width, height) = (300, 200) # Dimension of the window
screen = pygame.display.set_mode((width, height))
import engine # engine.so
b_running = True
while b_running:
# Quit when 'X' button is pressed.
for event in pygame.event.get():
if event.type == pygame.QUIT:
b_running = False
# Add some amount of delay.
pygame.time.wait(50)
# Give the buffer object to C.
engine.paint_gray(screen.get_buffer())
pygame.display.flip()
这里的关键是:
engine.paint_gray(screen.get_buffer())
这不完全是您所做的,但我认为您应该在 Python 应用程序中保留循环以便能够处理事件。 因此,这个 function 只是在缓冲区上绘制。 这是在 C 中实现的方式:
// Related: https://docs.python.org/3/extending/extending.html
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <stdint.h>
#include <assert.h>
static PyObject* engine_paint_gray(PyObject *self, PyObject *args)
{
Py_buffer buffer;
if (!PyArg_ParseTuple(args, "s*", &buffer))
assert(0);
uint8_t *raw_buffer = buffer.buf;
for (int index=0; index<buffer.len; ++index)
raw_buffer[index] = 127;
return Py_None;
}
static PyMethodDef EngineMethods[] = {
{"paint_gray", engine_paint_gray, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL} /* sentinel */
};
static struct PyModuleDef enginemodule = {
PyModuleDef_HEAD_INIT,
"engine",
NULL,
-1,
EngineMethods
};
PyMODINIT_FUNC
PyInit_engine(void)
{
return PyModule_Create(&enginemodule);
}
请注意,我也在调用pygame.display.flip()
。 这是必要的,因为 pygame 保留了两个缓冲区,一个在屏幕上绘制的前缓冲区和一个可以修改的后缓冲区。
大多数 GUI 工具包和游戏库将提供一种或另一种访问像素缓冲区的方法。
一个简单的入门方法是使用 pygame。 pygame 的Surface
的get_buffer().raw
数组可以传入 C 程序。
import pygame
background_colour = (255,255,255) # For the background color of your window
(width, height) = (300, 200) # Dimension of the window
screen = pygame.display.set_mode((width, height))
f = CDLL('engine.so')
f.loop(screen.get_buffer().raw)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.