Skip to content

Commit 11ce40b

Browse files
committed
C_CPP: Support BindPython Function
1 parent 621680d commit 11ce40b

File tree

1 file changed

+93
-8
lines changed

1 file changed

+93
-8
lines changed

src/libasr/codegen/asr_to_c_cpp.h

Lines changed: 93 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,86 @@ R"(#include <stdio.h>
502502
return "\ntemplate <" + template_for_Kokkos + ">\n" + func;
503503
}
504504

505+
std::string get_arg_conv_bind_python(const ASR::Function_t &x) {
506+
// args for bind python not yet supported
507+
LCOMPILERS_ASSERT(x.n_args == 0);
508+
509+
std::string arg_conv = R"(
510+
pArgs = PyTuple_New()" + std::to_string(x.n_args) + R"();
511+
)";
512+
for (size_t i = 0; i < x.n_args; ++i) {
513+
arg_conv += R"(
514+
// Use appropriate Py* Function for x.m_arg[i] conversion
515+
pValue = PyLong_FromLong(x.m_arg[i]);
516+
if (!pValue) {
517+
Py_DECREF(pArgs);
518+
Py_DECREF(pModule);
519+
fprintf(stderr, "Cannot convert argument\n");
520+
exit(1);
521+
}
522+
/* pValue reference stolen here: */
523+
PyTuple_SetItem(pArgs, )" + std::to_string(i) + R"(, pValue);
524+
)";
525+
}
526+
return arg_conv;
527+
}
528+
529+
std::string get_func_body_bind_python(const ASR::Function_t &x) {
530+
user_headers.insert("Python.h");
531+
std::string indent(indentation_level*indentation_spaces, ' ');
532+
std::string var_decls = "PyObject *pName, *pModule, *pFunc; PyObject *pArgs, *pValue;\n";
533+
std::string func_body = R"(
534+
/*
535+
Python Environment initialization and function evaluation
536+
should ideally happen once and not for every function call
537+
*/
538+
539+
Py_Initialize();
540+
wchar_t* argv1 = Py_DecodeLocale("", NULL);
541+
wchar_t** argv = {&argv1};
542+
PySys_SetArgv(1, argv);
543+
pName = PyUnicode_FromString(")" + std::string(x.m_module_file) + R"(");
544+
// TODO: check for error in pName
545+
546+
pModule = PyImport_Import(pName);
547+
Py_DECREF(pName);
548+
if (pModule == NULL) {
549+
PyErr_Print();
550+
fprintf(stderr, "Failed to load python module )" + std::string(x.m_module_file) + R"(\n");
551+
exit(1);
552+
}
553+
554+
pFunc = PyObject_GetAttrString(pModule, ")" + std::string(x.m_name) + R"(");
555+
if (!pFunc || !PyCallable_Check(pFunc)) {
556+
if (PyErr_Occurred()) PyErr_Print();
557+
fprintf(stderr, "Cannot find function )" + std::string(x.m_name) + R"(\n");
558+
Py_XDECREF(pFunc);
559+
Py_DECREF(pModule);
560+
exit(1);
561+
}
562+
563+
)" + get_arg_conv_bind_python(x) + R"(
564+
565+
pValue = PyObject_CallObject(pFunc, pArgs);
566+
Py_DECREF(pArgs);
567+
if (pValue == NULL) {
568+
Py_DECREF(pFunc);
569+
Py_DECREF(pModule);
570+
PyErr_Print();
571+
fprintf(stderr,"Call failed\n");
572+
exit(1);
573+
}
574+
// TODO: handle/convert the return value here
575+
Py_DECREF(pValue);
576+
577+
if (Py_FinalizeEx() < 0) {
578+
fprintf(stderr,"BindPython: Unknown Error\n");
579+
exit(1);
580+
}
581+
)";
582+
return "{\n" + indent + var_decls + func_body + "}\n";
583+
}
584+
505585
std::string declare_all_functions(const SymbolTable &scope) {
506586
std::string code, t;
507587
for (auto &item : scope.get_scope()) {
@@ -551,14 +631,19 @@ R"(#include <stdio.h>
551631
return;
552632
}
553633
ASR::FunctionType_t *f_type = ASRUtils::get_FunctionType(x);
554-
if (f_type->m_abi == ASR::abiType::BindC
555-
&& f_type->m_deftype == ASR::deftypeType::Interface) {
556-
if (x.m_module_file) {
557-
user_headers.insert(std::string(x.m_module_file));
558-
src = "";
559-
return;
560-
} else {
561-
sub += ";\n";
634+
if (f_type->m_deftype == ASR::deftypeType::Interface) {
635+
if (f_type->m_abi == ASR::abiType::BindC) {
636+
if (x.m_module_file) {
637+
user_headers.insert(std::string(x.m_module_file));
638+
src = "";
639+
return;
640+
} else {
641+
sub += ";\n";
642+
}
643+
} else if (f_type->m_abi == ASR::abiType::BindPython) {
644+
indentation_level += 1;
645+
sub += "\n" + get_func_body_bind_python(x);
646+
indentation_level -= 1;
562647
}
563648
} else {
564649
sub += "\n";

0 commit comments

Comments
 (0)