Skip to content

Commit b264035

Browse files
fix getClassName for compiled files (#24)
1 parent cf6bc1d commit b264035

File tree

1 file changed

+48
-12
lines changed

1 file changed

+48
-12
lines changed

pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.cpp

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,55 @@ inline std::string getline(const std::string& fileName)
2424
return line;
2525
}
2626

27-
inline std::string findClassName(const std::string& fileName)
28-
{
29-
std::string line;
30-
std::ifstream infile(fileName);
31-
std::string regexStr(R"(^class (\w+)\(\s*Fmi3Slave\s*\)\s*:)");
32-
while (getline(infile, line)) {
33-
std::smatch m;
34-
std::regex re(regexStr);
35-
if (std::regex_search(line, m, re)) {
36-
return m[1];
27+
std::string getClassName(PyObject * pModule)
28+
{
29+
std::string className = "";
30+
PyObject* dict = PyModule_GetDict(pModule);
31+
PyObject* keys = PyDict_Keys(dict);
32+
// Iterate through the dictionary keys to find classes derived from Fmi3Slave
33+
for (int i = 0; i < PyList_Size(keys); i++) {
34+
PyObject* key = PyList_GetItem(keys, i);
35+
if (PyUnicode_Check(key)) {
36+
PyObject* utf8Str = PyUnicode_AsEncodedString(key, "utf-8", nullptr);
37+
if (utf8Str == nullptr) {
38+
return "";
39+
}
40+
std::string classNameCandidate = PyBytes_AsString(utf8Str);
41+
Py_DECREF(utf8Str);
42+
43+
// Check if the class is a subclass of Fmi3Slave
44+
PyObject* obj = PyDict_GetItem(dict, key);
45+
if (PyObject_HasAttrString(obj, "__bases__")) {
46+
PyObject* bases = PyObject_GetAttrString(obj, "__bases__");
47+
if (PyTuple_Check(bases)) {
48+
for (int j = 0; j < PyTuple_Size(bases); j++) {
49+
PyObject* base = PyTuple_GetItem(bases, j);
50+
PyObject* baseNameObj = PyObject_GetAttrString(base, "__name__");
51+
if (baseNameObj && PyUnicode_Check(baseNameObj)) {
52+
PyObject* baseUtf8Str = PyUnicode_AsEncodedString(baseNameObj, "utf-8", nullptr);
53+
if (baseUtf8Str != nullptr) {
54+
std::string baseName = PyBytes_AsString(baseUtf8Str);
55+
Py_DECREF(baseUtf8Str);
56+
if (baseName == "Fmi3Slave") {
57+
className = classNameCandidate;
58+
Py_DECREF(baseNameObj);
59+
Py_DECREF(bases);
60+
break;
61+
}
62+
}
63+
Py_DECREF(baseNameObj);
64+
}
65+
}
66+
}
67+
Py_DECREF(bases);
68+
}
69+
70+
if (!className.empty()) {
71+
break; // Break after finding the first subclass
72+
}
3773
}
3874
}
39-
return "";
75+
return className;
4076
}
4177

4278
inline void py_safe_run(const std::function<void(PyGILState_STATE gilState)>& f)
@@ -77,7 +113,7 @@ PySlaveInstance::PySlaveInstance(std::string instanceName, std::string resources
77113
handle_py_exception("[ctor] PyImport_ImportModule", gilState);
78114
}
79115

80-
std::string className = findClassName(resources_ + "/" + moduleName + ".py");
116+
std::string className = getClassName(pModule);
81117
if (className.empty()) {
82118
cleanPyObject();
83119
throw cppfmu::FatalError("Unable to find class extending Fmi3Slave!");

0 commit comments

Comments
 (0)