1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2012-2014 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Support for nesting C code within a Nit program using its FFI
22 redef class FFILanguageAssignationPhase
23 var c_language
: FFILanguage = new CLanguage(self)
29 redef fun identify_language
(n
) do return n
.is_c
31 redef fun compile_module_block
(block
, ecc
, mmodule
)
33 if block
.is_c_header
then
34 ecc
.header_custom
.add block
.location
.as_line_pragma
35 ecc
.header_custom
.add
"\n"
36 ecc
.header_custom
.add block
.code
37 else if block
.is_c_body
then
38 ecc
.body_impl
.add block
.location
.as_line_pragma
39 ecc
.body_impl
.add
"\n"
40 ecc
.body_impl
.add block
.code
44 redef fun compile_extern_method
(block
, m
, ecc
, mmodule
)
46 var fc
= new ExternCFunction(m
, mmodule
)
47 fc
.decls
.add
( block
.location
.as_line_pragma
)
48 fc
.exprs
.add
( block
.code
)
49 ecc
.add_exported_function
( fc
)
52 redef fun compile_extern_class
(block
, m
, ecc
, mmodule
) do end
54 redef fun get_ftype
(block
, m
) do return new ForeignCType(block
.code
)
56 redef fun compile_callback
(callback
, mmodule
, mainmodule
, ecc
)
58 callback
.compile_callback_to_c
(mainmodule
, ecc
)
62 redef class AExternCodeBlock
63 fun is_c
: Bool do return language_name
== null or
64 language_name_lowered
== "c" or language_name_lowered
.has_prefix
( "c " )
66 fun is_c_body
: Bool do return language_name
== null or
67 language_name_lowered
== "c" or language_name_lowered
== "c body"
69 fun is_c_header
: Bool do return language_name_lowered
== "c header"
73 fun as_line_pragma
: String do return "#line {line_start-1} \"{file.filename}\
"\n"
77 # FIXME make nullable the key of `cflags`, `ldflags` and `cppflags` when
78 # supported by the bootstrap
80 # Custom options for the C compiler (CFLAGS)
81 var cflags
= new MultiHashMap[String, String]
83 # Custom options for the C linker (LDFLAGS)
84 var ldflags
= new MultiHashMap[String, String]
86 # Additional libraries needed for the compilation
87 # Will be used with pkg-config
88 var pkgconfigs
= new Array[String]
94 redef var ctype
: String
97 redef class NitniCallback
98 fun compile_callback_to_c
(mmodule
: MModule, ffi_ccu
: CCompilationUnit) do end
102 # Context when calling user C code from generated code
103 fun to_c_call_context
: ToCCallContext do return once
new ToCCallContext
105 # Context when calling generated code from user C code
106 fun from_c_call_context
: FromCCallContext do return once
new FromCCallContext
109 redef class MExplicitCall
110 redef fun compile_callback_to_c
(mmodule
, ffi_ccu
)
112 var mproperty
= mproperty
.as(MMethod)
114 var full_cname
= mproperty
.build_cname
(recv_mtype
, mmodule
, null, long_signature
)
115 var friendly_cname
= mproperty
.build_cname
(recv_mtype
, mmodule
, null, short_signature
)
116 ffi_ccu
.body_decl
.add
("#define {friendly_cname} {full_cname}\n")
120 # Context when calling user C code from generated code
124 # TODO: private init because singleton instance (see `to_c_call_context`)
126 redef fun name_mtype
(mtype
)
128 if mtype
isa MClassType and mtype
.mclass
.kind
== extern_kind
then return "void *"
133 # Context when calling generated code from user C code
134 class FromCCallContext
137 # TODO: private init because singleton instance (see `from_c_call_context`)
139 redef fun name_mtype
(mtype
) do return mtype
.cname
142 class ExternCFunction
145 var method
: AMethPropdef
147 init (method
: AMethPropdef, mmodule
: MModule)
151 var recv_mtype
= method
.mpropdef
.mclassdef
.bound_mtype
152 var csignature
= method
.mpropdef
.mproperty
.build_csignature
(recv_mtype
, mmodule
, "___impl", long_signature
, from_c_call_context
)