Skip to content

Instantly share code, notes, and snippets.

@jmccardle
Created February 15, 2023 01:43
Show Gist options
  • Save jmccardle/7953b68d27efa430a50a03e1ba4d9ac5 to your computer and use it in GitHub Desktop.
Save jmccardle/7953b68d27efa430a50a03e1ba4d9ac5 to your computer and use it in GitHub Desktop.
// Python script engine includes
#include <Python.h>
#include <iostream>
#include <stdlib.h>
#include <vector>
// SFML
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
sf::RenderWindow window;
sf::Font font;
sf::Text text;
// TCOD
#include <libtcod.hpp>
// init_python - configure interpreter details here
PyStatus init_python(const char *program_name)
{
PyStatus status;
PyConfig config;
PyConfig_InitPythonConfig(&config);
/* Set the program name before reading the configuration
(decode byte string from the locale encoding).
Implicitly preinitialize Python. */
status = PyConfig_SetBytesString(&config, &config.program_name,
program_name);
//if (PyStatus_Exception(status)) {
// goto done;
//}
/* Read all configuration at once */
status = PyConfig_Read(&config);
//if (PyStatus_Exception(status)) {
// goto done;
//}
/* Specify sys.path explicitly */
/* If you want to modify the default set of paths, finish
initialization first and then use PySys_GetObject("path") */
config.module_search_paths_set = 1;
const wchar_t* str_arr[] = {
L"./Python-3.11.1/build/lib.linux-x86_64-3.11",
L"./Python-3.11.1/Lib",
L"./Python-3.11.1/Modules",
L".",
L"./venv/lib/python3.11/site-packages"
};
for(auto s : str_arr) {
status = PyWideStringList_Append(&config.module_search_paths, s);
if (PyStatus_Exception(status)) {
break;
}
}
status = Py_InitializeFromConfig(&config);
done:
PyConfig_Clear(&config);
return status;
}
// C++ example functionality
int recurse_fib(int i)
{
if (i <= 1) return 1;
return recurse_fib(i-1) + recurse_fib(i-2);
}
// Create a python module to expose C++ functionality
static PyObject* scriptable_fibonacci(PyObject *self, PyObject *args)
{
int x;
// get input (single integer) from args
if (!PyArg_ParseTuple(args, "i", &x)) return NULL;
return PyLong_FromLong(recurse_fib(x));
}
static PyMethodDef scriptableMethods[] = {
{"fibonacci", scriptable_fibonacci, METH_VARARGS,
"Fibonacci sequence by index"},
{NULL, NULL, 0, NULL}
};
static PyModuleDef scriptableModule = {
PyModuleDef_HEAD_INIT, "scriptable", NULL, -1, scriptableMethods,
NULL, NULL, NULL, NULL
};
static PyObject* PyInit_scriptable(void)
{
return PyModule_Create(&scriptableModule);
}
int main()
{
std::cout << "[C++] Initializing Python\n";
setenv("PYTHONHOME", "./Python-3.11.1", 0);
//Express this program as a module before pyinit
PyImport_AppendInittab("scriptable", &PyInit_scriptable);
//Initialize the python instance
PyStatus status = init_python("test");
Py_Initialize();
// SFML demo setup
font.loadFromFile("JetbrainsMono.ttf");
window.create(sf::VideoMode(640, 480), "Python/SFML/TCOD test");
// TCOD demo setup
//Run a simple string
//PyRun_SimpleString("from time import time,ctime\n"
// "print('Today is',ctime(time()))\n");
std::cout << "[C++] Executing engine_user.py\n";
FILE* PScriptFile = fopen("engine_user.py", "r");
if(PScriptFile) {
PyRun_SimpleFile(PScriptFile, "engine_user.py");
fclose(PScriptFile);
}
/*
std::cout << "[C++] Executing Python string\n";
PyRun_SimpleString("import sys;print(sys.version)");
//Run a simple file
std::cout << "[C++] executing the contents of test.py\n";
FILE* PScriptFile = fopen("test.py", "r");
if(PScriptFile){
PyRun_SimpleFile(PScriptFile, "test.py");
fclose(PScriptFile);
}
std::cout << "[C++] importing script.script_function and executing from C++. Aquiring GIL...\n";
//Run a python function
PyObject *pName, *pModule, *pFunc, *pArgs, *pValue;
pName = PyUnicode_FromString((char*)"script");
// acquire GIL
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
pModule = PyImport_Import(pName);
pFunc = PyObject_GetAttrString(pModule, (char*)"script_function");
pArgs = PyTuple_Pack(1, PyUnicode_FromString((char*)"Embedded Python"));
pValue = PyObject_CallObject(pFunc, pArgs);
std::cout << "[C++] Result:\n";
auto result = _PyUnicode_AsString(pValue);
std::cout << result << std::endl;
// release GIL
PyGILState_Release(gstate);
*/
// TCOD functionality - gather noise
TCODNoise noise_{2, TCOD_NOISE_SIMPLEX};
float hurst_ = TCOD_NOISE_DEFAULT_HURST;
float lacunarity_ = TCOD_NOISE_DEFAULT_LACUNARITY;
noise_ = TCODNoise(2, hurst_, lacunarity_);
float display_noise[64][48];
int generated = 0;
float n_min = 0, n_max = 0;
for (int x = 0; x < 64; x++) {
for (int y = 0; y < 48; y++) {
float f[2] = {float(x * 10 + 5) / 100.0, float(y * 10 + 5) / 100.0};
display_noise[x][y] = float(noise_.get(f, TCOD_NOISE_SIMPLEX));
//display_noise[x][y] = float(rand()) / RAND_MAX;
generated++;
if (display_noise[x][y] > n_max) n_max = display_noise[x][y];
else if (display_noise[x][y] < n_min) n_min = display_noise[x][y];
}
}
std::cout << "Generated " << generated << " points of noise: "
<< n_min << " - " << n_max << std::endl;
// SFML/graphical run
window.setFramerateLimit(30);
text.setFont(font);
text.setString("asdf");
text.setCharacterSize(16);
bool running = true;
while (running) {
// render
window.clear();
// draw boxes of noise
for (int x = 0; x < 64; x++) {
for (int y = 0; y < 48; y++) {
//int x1 = x * 10, x2 = (x+1) * 10, y1 = y * 10, y2 = (y+1) * 10;
sf::RectangleShape r;
r.setPosition(sf::Vector2f(x * 10, y * 10));
r.setSize(sf::Vector2f(10, 10));
r.setOutlineThickness(0);
r.setFillColor(sf::Color(display_noise[x][y] * 255, 0, 0));
window.draw(r);
}
}
window.draw(text);
window.display();
// user input
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) { running = false; continue; }
}
}
//Close the python instance
Py_Finalize();
std::cout << "[C++] Exiting normally.\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment