Skip to content

Commit 3594862

Browse files
committed
C_CPP: Support args and return val for simple types
1 parent 3d19b8a commit 3594862

File tree

2 files changed

+103
-9
lines changed

2 files changed

+103
-9
lines changed

src/libasr/codegen/asr_to_c_cpp.h

Lines changed: 22 additions & 9 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,13 @@ 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+
return "\n " + CUtils::get_c_type_from_ttype_t(r_v->m_type) + " " + std::string(r_v->m_name) + " = " +
532+
CUtils::get_py_obj_return_type_conv_func_from_ttype_t(r_v->m_type) + "(pValue);";
533+
}
534+
529535
std::string get_func_body_bind_python(const ASR::Function_t &x) {
530536
user_headers.insert("Python.h");
531537
std::string indent(indentation_level*indentation_spaces, ' ');
@@ -540,8 +546,13 @@ R"(#include <stdio.h>
540546
wchar_t* argv1 = Py_DecodeLocale("", NULL);
541547
wchar_t** argv = {&argv1};
542548
PySys_SetArgv(1, argv);
549+
543550
pName = PyUnicode_FromString(")" + std::string(x.m_module_file) + R"(");
544-
// TODO: check for error in pName
551+
if (pName == NULL) {
552+
PyErr_Print();
553+
fprintf(stderr, "Failed to convert to unicode string )" + std::string(x.m_module_file) + R"(\n");
554+
exit(1);
555+
}
545556
546557
pModule = PyImport_Import(pName);
547558
Py_DECREF(pName);
@@ -559,9 +570,7 @@ R"(#include <stdio.h>
559570
Py_DECREF(pModule);
560571
exit(1);
561572
}
562-
563-
)" + get_arg_conv_bind_python(x) + R"(
564-
573+
)" + get_arg_conv_bind_python(x) + R"(
565574
pValue = PyObject_CallObject(pFunc, pArgs);
566575
Py_DECREF(pArgs);
567576
if (pValue == NULL) {
@@ -571,14 +580,18 @@ R"(#include <stdio.h>
571580
fprintf(stderr,"Call failed\n");
572581
exit(1);
573582
}
574-
// TODO: handle/convert the return value here
583+
)" + get_return_value_conv_bind_python(x) + R"(
575584
Py_DECREF(pValue);
576585
577586
if (Py_FinalizeEx() < 0) {
578587
fprintf(stderr,"BindPython: Unknown Error\n");
579588
exit(1);
580589
}
581590
)";
591+
if (x.m_return_var) {
592+
auto r_v = ASRUtils::EXPR2VAR(x.m_return_var);
593+
func_body += "\n return " + std::string(r_v->m_name) + ";\n";
594+
}
582595
return "{\n" + indent + var_decls + func_body + "}\n";
583596
}
584597

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)