Skip to content

Commit ccf52ab

Browse files
committed
C_CPP: Support args and return val for simple types
1 parent 6a693b3 commit ccf52ab

File tree

2 files changed

+110
-11
lines changed

2 files changed

+110
-11
lines changed

src/libasr/codegen/asr_to_c_cpp.h

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -503,16 +503,15 @@ R"(#include <stdio.h>
503503
}
504504

505505
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);
508506

509507
std::string arg_conv = R"(
510508
pArgs = PyTuple_New()" + std::to_string(x.n_args) + R"();
511509
)";
512510
for (size_t i = 0; i < x.n_args; ++i) {
511+
ASR::Variable_t *arg = ASRUtils::EXPR2VAR(x.m_args[i]);
513512
arg_conv += R"(
514-
// Use appropriate Py* Function for x.m_arg[i] conversion
515-
pValue = PyLong_FromLong(x.m_arg[i]);
513+
pValue = )" + CUtils::get_py_obj_type_conv_func_from_ttype_t(arg->m_type) + "("
514+
+ std::string(arg->m_name) + R"();
516515
if (!pValue) {
517516
Py_DECREF(pArgs);
518517
Py_DECREF(pModule);
@@ -526,6 +525,20 @@ R"(#include <stdio.h>
526525
return arg_conv;
527526
}
528527

528+
std::string get_return_value_conv_bind_python(const ASR::Function_t &x) {
529+
if (!x.m_return_var) return "";
530+
ASR::Variable_t* r_v = ASRUtils::EXPR2VAR(x.m_return_var);
531+
std::string indent = "\n ";
532+
std::string py_val_cnvrt = CUtils::get_py_obj_return_type_conv_func_from_ttype_t(r_v->m_type) + "(pValue)";
533+
std::string ret_var_decl = indent + CUtils::get_c_type_from_ttype_t(r_v->m_type) + " " + std::string(r_v->m_name) + ";";
534+
std::string ret_stmt = indent + std::string(r_v->m_name) + " = " + py_val_cnvrt + ";";
535+
std::string clear_pValue = "";
536+
if (!ASRUtils::is_aggregate_type(r_v->m_type)) {
537+
clear_pValue = indent + "Py_DECREF(pValue);";
538+
}
539+
return ret_var_decl + ret_stmt + clear_pValue + "\n";
540+
}
541+
529542
std::string get_func_body_bind_python(const ASR::Function_t &x) {
530543
user_headers.insert("Python.h");
531544
std::string indent(indentation_level*indentation_spaces, ' ');
@@ -540,8 +553,13 @@ R"(#include <stdio.h>
540553
wchar_t* argv1 = Py_DecodeLocale("", NULL);
541554
wchar_t** argv = {&argv1};
542555
PySys_SetArgv(1, argv);
556+
543557
pName = PyUnicode_FromString(")" + std::string(x.m_module_file) + R"(");
544-
// TODO: check for error in pName
558+
if (pName == NULL) {
559+
PyErr_Print();
560+
fprintf(stderr, "Failed to convert to unicode string )" + std::string(x.m_module_file) + R"(\n");
561+
exit(1);
562+
}
545563
546564
pModule = PyImport_Import(pName);
547565
Py_DECREF(pName);
@@ -559,9 +577,7 @@ R"(#include <stdio.h>
559577
Py_DECREF(pModule);
560578
exit(1);
561579
}
562-
563-
)" + get_arg_conv_bind_python(x) + R"(
564-
580+
)" + get_arg_conv_bind_python(x) + R"(
565581
pValue = PyObject_CallObject(pFunc, pArgs);
566582
Py_DECREF(pArgs);
567583
if (pValue == NULL) {
@@ -571,14 +587,16 @@ R"(#include <stdio.h>
571587
fprintf(stderr,"Call failed\n");
572588
exit(1);
573589
}
574-
// TODO: handle/convert the return value here
575-
Py_DECREF(pValue);
576-
590+
)" + get_return_value_conv_bind_python(x) + R"(
577591
if (Py_FinalizeEx() < 0) {
578592
fprintf(stderr,"BindPython: Unknown Error\n");
579593
exit(1);
580594
}
581595
)";
596+
if (x.m_return_var) {
597+
auto r_v = ASRUtils::EXPR2VAR(x.m_return_var);
598+
func_body += "\n return " + std::string(r_v->m_name) + ";\n";
599+
}
582600
return "{\n" + indent + var_decls + func_body + "}\n";
583601
}
584602

src/libasr/codegen/c_utils.h

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,87 @@ namespace CUtils {
330330
return type_src;
331331
}
332332

333+
static inline std::string get_py_obj_type_conv_func_from_ttype_t(ASR::ttype_t* t) {
334+
int kind = ASRUtils::extract_kind_from_ttype_t(t);
335+
std::string type_src = "";
336+
switch( t->type ) {
337+
case ASR::ttypeType::Integer: {
338+
switch (kind)
339+
{
340+
case 4: type_src = "PyLong_FromLong"; break;
341+
case 8: type_src = "PyLong_FromLongLong"; break;
342+
default:
343+
throw CodeGenError("get_py_obj_type_conv_func: Unsupported kind in int type");
344+
}
345+
break;
346+
}
347+
case ASR::ttypeType::UnsignedInteger: {
348+
switch (kind)
349+
{
350+
case 4: type_src = "PyLong_FromUnsignedLong"; break;
351+
case 8: type_src = "PyLong_FromUnsignedLongLong"; break;
352+
default:
353+
throw CodeGenError("get_py_obj_type_conv_func: Unsupported kind in unsigned int type");
354+
}
355+
break;
356+
}
357+
case ASR::ttypeType::Logical: {
358+
type_src = "PyBool_FromLong";
359+
break;
360+
}
361+
case ASR::ttypeType::Real: {
362+
type_src = "PyFloat_FromDouble";
363+
break;
364+
}
365+
case ASR::ttypeType::Character: {
366+
type_src = "PyUnicode_FromString";
367+
break;
368+
}
369+
default: {
370+
throw CodeGenError("get_py_object_type_conv_func: Type " + ASRUtils::type_to_str_python(t) + " not supported yet.");
371+
}
372+
}
373+
return type_src;
374+
}
375+
376+
static inline std::string get_py_obj_return_type_conv_func_from_ttype_t(ASR::ttype_t* t) {
377+
int kind = ASRUtils::extract_kind_from_ttype_t(t);
378+
std::string type_src = "";
379+
switch( t->type ) {
380+
case ASR::ttypeType::Integer: {
381+
switch (kind)
382+
{
383+
case 4: type_src = "PyLong_AsLong"; break;
384+
case 8: type_src = "PyLong_AsLongLong"; break;
385+
default:
386+
throw CodeGenError("get_py_obj_type_conv_func: Unsupported kind in int type");
387+
}
388+
break;
389+
}
390+
case ASR::ttypeType::UnsignedInteger: {
391+
switch (kind)
392+
{
393+
case 4: type_src = "PyLong_AsUnsignedLong"; break;
394+
case 8: type_src = "PyLong_AsUnsignedLongLong"; break;
395+
default:
396+
throw CodeGenError("get_py_obj_type_conv_func: Unsupported kind in unsigned int type");
397+
}
398+
break;
399+
}
400+
case ASR::ttypeType::Real: {
401+
type_src = "PyFloat_AsDouble";
402+
break;
403+
}
404+
case ASR::ttypeType::Character: {
405+
type_src = "(char*)PyUnicode_AsUTF8";
406+
break;
407+
}
408+
default: {
409+
throw CodeGenError("get_py_object_type_conv_func: Type " + ASRUtils::type_to_str_python(t) + " not supported yet.");
410+
}
411+
}
412+
return type_src;
413+
}
333414
} // namespace CUtils
334415

335416

0 commit comments

Comments
 (0)