Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions integration_tests/run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
import sys

# LPython and CPython tests
tests = [
"exit_01.py",
"expr_01.py",
Expand All @@ -20,14 +21,15 @@
"test_math1.py"
]

# At present we run these tests on cpython, later we should also move to lpython
# CPython tests only
test_cpython = [
"test_generics_01.py"
"test_generics_01.py",
"test_c_interop_01.py"
]


def main():
print("Compiling...")
print("Compiling LPython tests...")
for pyfile in tests:
basename = os.path.splitext(pyfile)[0]
cmd = os.path.join("..", "src", "bin", "lpython") + " %s -o %s" % (pyfile, basename)
Expand All @@ -39,7 +41,7 @@ def main():
print("Command '%s' failed." % cmd)
sys.exit(1)

print("Running...")
print("Running LPython and CPython tests...")
python_path="src/runtime/ltypes"
for pyfile in tests:
basename = os.path.splitext(pyfile)[0]
Expand All @@ -57,7 +59,7 @@ def main():
print("Command '%s' failed." % cmd)
sys.exit(1)

print("Running cpython tests...")
print("Running CPython tests...")
for pyfile in test_cpython:
cmd = "PYTHONPATH=%s python integration_tests/%s" % (python_path,
pyfile)
Expand Down
15 changes: 15 additions & 0 deletions integration_tests/test_c_interop_01.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from ltypes import ccall, f64, f32
from math import pi

@ccall
def _lfortran_dsin(x: f64) -> f64:
pass

@ccall
def _lfortran_ssin(x: f32) -> f32:
pass

assert abs(_lfortran_dsin(pi) - 0) < 1e-12
assert abs(_lfortran_dsin(pi/2) - 1) < 1e-12
assert abs(_lfortran_ssin(pi) - 0) < 1e-6
assert abs(_lfortran_ssin(pi/2) - 1) < 1e-6
61 changes: 60 additions & 1 deletion src/runtime/ltypes/ltypes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from inspect import getfullargspec, getcallargs
from typing import types
import os
import ctypes
import platform

# data-types

Expand All @@ -10,7 +13,7 @@
c32 = types.new_class("c32")
c64 = types.new_class("c64")

# overloading support
# Overloading support

def ltype(x):
"""
Expand Down Expand Up @@ -70,3 +73,59 @@ def __call__(self, *args, **kwargs):
def overload(f):
overloaded_f = OverloadedFunction(f)
return overloaded_f



# C interoperation support

class CTypes:
"""
A wrapper class for interfacing C via ctypes.
"""

def __init__(self, f):
def convert_type_to_ctype(arg):
if arg == f64:
return ctypes.c_double
elif arg == f32:
return ctypes.c_float
else:
raise NotImplementedError("Type not implemented")
def get_rtlib_dir():
current_dir = os.path.dirname(os.path.abspath(__file__))
return os.path.join(current_dir, "..")
def get_crtlib_name():
if platform.system() == "Linux":
return "liblfortran_runtime.so"
elif platform.system() == "Darwin":
return "liblfortran_runtime.dylib"
elif platform.system() == "Windows":
return "lfortran_runtime.dll"
else:
raise NotImplementedError("Platform not implemented")
def get_crtlib_path():
return os.path.join(get_rtlib_dir(), get_crtlib_name())
self.name = f.__name__
self.args = f.__code__.co_varnames
self.annotations = f.__annotations__
Comment thread
certik marked this conversation as resolved.
Resolved
crtlib = get_crtlib_path()
self.library = ctypes.CDLL(crtlib)
self.cf = self.library[self.name]
argtypes = []
for arg in self.args:
arg_type = self.annotations[arg]
arg_ctype = convert_type_to_ctype(arg_type)
argtypes.append(arg_ctype)
self.cf.argtypes = argtypes
res_type = self.annotations["return"]
self.cf.restype = convert_type_to_ctype(res_type)

def __call__(self, *args, **kwargs):
if len(kwargs) > 0:
raise Exception("kwargs are not supported")
return self.cf(*args)


def ccall(f):
wrapped_f = CTypes(f)
return wrapped_f