[英]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.