mql5/Experts/Advisors/DualEA/dll/feature_export_dll.cpp

50 lines
2.1 KiB
C++
Raw Permalink Normal View History

2025-09-20 02:25:58 -04:00
// feature_export_dll.cpp
// Full C++ DLL implementation (stdcall, Python embedding, raw protobuf bytes)
// Compile with: cl /LD feature_export_dll.cpp /I<python_include> /link /LIBPATH:<python_lib> python3x.lib
#include <windows.h>
#include <Python.h>
#include <string>
2025-10-03 01:38:10 -04:00
#include <stdexcept>
#include <cstring>
2025-09-20 02:25:58 -04:00
// Helper: Convert UTF-8 std::string to wide string
std::wstring utf8_to_wide(const std::string& str) {
int size_needed = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
}
extern "C" __declspec(dllexport) int __stdcall ExportFeatureBatch(const void* pb_bytes, int pb_len, char* out_path, int out_path_len) {
int result = 0;
Py_Initialize();
try {
PyObject* sys_path = PySys_GetObject("path");
PyList_Append(sys_path, PyUnicode_FromString("./python")); // or absolute path
PyObject* module = PyImport_ImportModule("feature_export");
if (!module) throw std::runtime_error("Could not import feature_export.py");
PyObject* func = PyObject_GetAttrString(module, "write_batches_to_parquet");
if (!func || !PyCallable_Check(func)) throw std::runtime_error("No write_batches_to_parquet");
PyObject* py_bytes = PyBytes_FromStringAndSize((const char*)pb_bytes, pb_len);
PyObject* args = PyTuple_Pack(1, py_bytes);
PyObject* ret = PyObject_CallObject(func, args);
if (!ret) throw std::runtime_error("Python call failed");
const char* path = PyUnicode_AsUTF8(ret);
if (!path) throw std::runtime_error("Return value not string");
strncpy(out_path, path, out_path_len - 1);
out_path[out_path_len - 1] = '\0';
Py_XDECREF(ret);
Py_XDECREF(args);
Py_XDECREF(py_bytes);
Py_XDECREF(func);
Py_XDECREF(module);
} catch (...) {
result = -1;
}
Py_Finalize();
return result;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
return TRUE;
}