簡體   English   中英

如何 map 視頻 memory 從 python 到 Z4A8A08F09D37B73795649038408B5F3

[英]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 應用程序共享一個緩沖區。 有一個緩沖區協議就是為了這個目的而存在的。 本質上,您共享一個具有buflen字段的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 的Surfaceget_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM