mirror of
https://github.com/EiffelSoftware/eiffel-org.git
synced 2025-12-08 07:42:33 +01:00
Author:halw
Date:2008-12-01T22:45:08.000000Z git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@112 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
@@ -19,12 +19,12 @@ Generally, you should use these types when implementing external C functions bou
|
||||
{{sample|Calling C external `foo' from Eiffel, which takes a pointer and an eiffel object of type OBJECT as arguments and returns an INTEGER. }}
|
||||
<div>
|
||||
<code>
|
||||
c_foo (ptr: POINTER; obj: OBJECT): INTEGER is
|
||||
external
|
||||
"C | %"your_file.h%""
|
||||
alias
|
||||
"foo"
|
||||
end
|
||||
c_foo (ptr: POINTER; obj: OBJECT): INTEGER
|
||||
external
|
||||
"C | %"your_file.h%""
|
||||
alias
|
||||
"foo"
|
||||
end
|
||||
</code>
|
||||
|
||||
|
||||
@@ -46,12 +46,12 @@ int foo (void *arg1, char c, FILE *file)
|
||||
</code>
|
||||
</div><div>To match the signature, you must declare it in Eiffel as:
|
||||
<code>
|
||||
c_foo (arg1: POINTER; c: CHARACTER; file: POINTER): INTEGER is
|
||||
external
|
||||
"C (void *, char, FILE *) : int | %""your_file.h%""
|
||||
alias
|
||||
"foo"
|
||||
end
|
||||
c_foo (arg1: POINTER; c: CHARACTER; file: POINTER): INTEGER
|
||||
external
|
||||
"C (void *, char, FILE *) : int | %""your_file.h%""
|
||||
alias
|
||||
"foo"
|
||||
end
|
||||
</code>
|
||||
</div>
|
||||
Not doing this would generally produce warnings during the C compilation, and it could crash with some C compilers.
|
||||
@@ -91,12 +91,12 @@ Use ''eif_access'' to pass an Eiffel object to an Eiffel routine or to return th
|
||||
'''For example, in the following external:'''
|
||||
|
||||
<code>
|
||||
c_foo (ptr: POINTER; obj: OBJECT): INTEGER is
|
||||
external
|
||||
"C | %""your_file.h%""
|
||||
alias
|
||||
"foo"
|
||||
end
|
||||
c_foo (ptr: POINTER; obj: OBJECT): INTEGER
|
||||
external
|
||||
"C | %""your_file.h%""
|
||||
alias
|
||||
"foo"
|
||||
end
|
||||
</code>
|
||||
|
||||
|
||||
@@ -191,18 +191,18 @@ Called within a C external, the function ''eif_adopt'' creates a user protection
|
||||
In Eiffel:
|
||||
<div>
|
||||
<code>
|
||||
c_foo (ptr: POINTER; obj: OBJECT): INTEGER is
|
||||
external
|
||||
"C | %"your_file.h%""
|
||||
alias
|
||||
"foo"
|
||||
end
|
||||
c_display_and_release_obj is
|
||||
external
|
||||
"C | %"your_file.h%""
|
||||
alias
|
||||
"display_and_release_obj"
|
||||
end
|
||||
c_foo (ptr: POINTER; obj: OBJECT): INTEGER
|
||||
external
|
||||
"C | %"your_file.h%""
|
||||
alias
|
||||
"foo"
|
||||
end
|
||||
c_display_and_release_obj
|
||||
external
|
||||
"C | %"your_file.h%""
|
||||
alias
|
||||
"display_and_release_obj"
|
||||
end
|
||||
</code>
|
||||
|
||||
</div>
|
||||
@@ -403,10 +403,10 @@ See also <eiffel>eif_access</eiffel>.
|
||||
|
||||
In Eiffel:
|
||||
<code>
|
||||
foo : STRING is
|
||||
external
|
||||
"C | %"a file.h%""
|
||||
end
|
||||
foo : STRING
|
||||
external
|
||||
"C | %"a file.h%""
|
||||
end
|
||||
</code>
|
||||
|
||||
In C:
|
||||
|
||||
@@ -108,19 +108,19 @@ For example, a C++ function
|
||||
|
||||
should have the Eiffel counterpart
|
||||
<code>
|
||||
cpp_add (obj: POINTER; new_int: INTEGER) is
|
||||
-- Encapsulation of member function add.
|
||||
external
|
||||
"C++ [IntArray %"intarray.h%"] (IntArray *, int)"
|
||||
end
|
||||
cpp_add (obj: POINTER; new_int: INTEGER)
|
||||
-- Encapsulation of member function add.
|
||||
external
|
||||
"C++ [IntArray %"intarray.h%"] (IntArray *, int)"
|
||||
end
|
||||
</code>
|
||||
This scheme, however, is often inconvenient because it forces the Eiffel side to work on objects in a non-object-oriented way. (The object-oriented way treats the current object, within a class, as implicit.) A better approach, used by Legacy++, is to make a feature such as cpp_add secret, and to export a feature whose signature corresponds to that of the original C++ function, with no extra object argument; that feature will use a secret attribute object_ptr to access the object. In the example this will give the feature
|
||||
<code>
|
||||
add (new_int: INTEGER) is
|
||||
-- Encapsulation of member function add.
|
||||
do
|
||||
cpp_add (object_ptr, new_int)
|
||||
end
|
||||
add (new_int: INTEGER)
|
||||
-- Encapsulation of member function add.
|
||||
do
|
||||
cpp_add (object_ptr, new_int)
|
||||
end
|
||||
</code>
|
||||
|
||||
where ''object_ptr'' is a secret attribute of type <eiffel>POINTER</eiffel>, initialized by the creation procedures of the class. To the Eiffel developer, <eiffel>add</eiffel> looks like a normal object-oriented feature, which takes only the expected argument. Further examples appear below. This technique only works of course when the C++ object is implicit in the context of the Eiffel class.
|
||||
@@ -198,101 +198,101 @@ class IntArray {
|
||||
Here is the result of applying Legacy++ to that class, which will serve as an illustration of both the C++ interface mechanisms and Legacy++:
|
||||
<code>
|
||||
indexing
|
||||
description: "Eiffel encapsulation of C++ class IntArray";
|
||||
date: "$Date: 2006-10-12 03:18:50 +0200 (Thu, 12 Oct 2006) $";
|
||||
revision: "$Revision: 64319 $"
|
||||
description: "Eiffel encapsulation of C++ class IntArray";
|
||||
date: "$Date: 2006-10-12 03:18:50 +0200 (Thu, 12 Oct 2006) $";
|
||||
revision: "$Revision: 64319 $"
|
||||
|
||||
class
|
||||
INTARRAY
|
||||
INTARRAY
|
||||
|
||||
inherit
|
||||
MEMORY
|
||||
redefine
|
||||
dispose
|
||||
end
|
||||
MEMORY
|
||||
redefine
|
||||
dispose
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
make
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make (size: INTEGER) is
|
||||
-- Create Eiffel and C++ objects.
|
||||
do
|
||||
object_ptr := cpp_new (size)
|
||||
end
|
||||
make (size: INTEGER)
|
||||
-- Create Eiffel and C++ objects.
|
||||
do
|
||||
object_ptr := cpp_new (size)
|
||||
end
|
||||
|
||||
feature-- Removal
|
||||
|
||||
dispose is
|
||||
-- Delete C++ object.
|
||||
do
|
||||
cpp_delete (object_ptr)
|
||||
end
|
||||
dispose
|
||||
-- Delete C++ object.
|
||||
do
|
||||
cpp_delete (object_ptr)
|
||||
end
|
||||
|
||||
feature
|
||||
|
||||
output is
|
||||
-- Call C++ counterpart.
|
||||
do
|
||||
cpp_output (object_ptr)
|
||||
end
|
||||
output
|
||||
-- Call C++ counterpart.
|
||||
do
|
||||
cpp_output (object_ptr)
|
||||
end
|
||||
|
||||
add (new_int: INTEGER) is
|
||||
-- Call C++ counterpart.
|
||||
do
|
||||
cpp_add (object_ptr, new_int)
|
||||
end
|
||||
add (new_int: INTEGER)
|
||||
-- Call C++ counterpart.
|
||||
do
|
||||
cpp_add (object_ptr, new_int)
|
||||
end
|
||||
|
||||
feature {INTARRAY}
|
||||
|
||||
underscore_integers: POINTER is
|
||||
-- Value of corresponding C++ data member.
|
||||
do
|
||||
Result := underscore_integers (object_ptr)
|
||||
end
|
||||
underscore_integers: POINTER
|
||||
-- Value of corresponding C++ data member.
|
||||
do
|
||||
Result := underscore_integers (object_ptr)
|
||||
end
|
||||
|
||||
feature {NONE} -- Externals
|
||||
|
||||
cpp_new (size: INTEGER): POINTER is
|
||||
-- Call single constructor of C++ class.
|
||||
external
|
||||
"C++ [new IntArray %"INTARRAY.H%"] (EIF_INTEGER)"
|
||||
end
|
||||
cpp_new (size: INTEGER): POINTER
|
||||
-- Call single constructor of C++ class.
|
||||
external
|
||||
"C++ [new IntArray %"INTARRAY.H%"] (EIF_INTEGER)"
|
||||
end
|
||||
|
||||
cpp_delete (cpp_obj: POINTER) is
|
||||
-- Call C++ destructor on C++ object.
|
||||
external
|
||||
"C++ [delete IntArray %"INTARRAY.H%"] ()"
|
||||
end
|
||||
cpp_delete (cpp_obj: POINTER)
|
||||
-- Call C++ destructor on C++ object.
|
||||
external
|
||||
"C++ [delete IntArray %"INTARRAY.H%"] ()"
|
||||
end
|
||||
|
||||
cpp_output (cpp_obj: POINTER) is
|
||||
-- Call C++ member function.
|
||||
external
|
||||
"C++ [IntArray %"INTARRAY.H%"] ()"
|
||||
alias
|
||||
"output"
|
||||
end
|
||||
cpp_output (cpp_obj: POINTER)
|
||||
-- Call C++ member function.
|
||||
external
|
||||
"C++ [IntArray %"INTARRAY.H%"] ()"
|
||||
alias
|
||||
"output"
|
||||
end
|
||||
|
||||
cpp_add (cpp_obj: POINTER; new_int: INTEGER) is
|
||||
-- Call C++ member function.
|
||||
external
|
||||
"C++ [IntArray %"INTARRAY.H%"] (EIF_INTEGER)"
|
||||
alias
|
||||
"add"
|
||||
end
|
||||
cpp_add (cpp_obj: POINTER; new_int: INTEGER)
|
||||
-- Call C++ member function.
|
||||
external
|
||||
"C++ [IntArray %"INTARRAY.H%"] (EIF_INTEGER)"
|
||||
alias
|
||||
"add"
|
||||
end
|
||||
|
||||
cpp_underscore_integers (cpp_obj: POINTER): POINTER is
|
||||
-- Value of C++ data member
|
||||
external
|
||||
"C++ [data_member IntArray %"INTARRAY.H%"]: EIF_POINTER"
|
||||
alias
|
||||
"_integers"
|
||||
end
|
||||
cpp_underscore_integers (cpp_obj: POINTER): POINTER
|
||||
-- Value of C++ data member
|
||||
external
|
||||
"C++ [data_member IntArray %"INTARRAY.H%"]: EIF_POINTER"
|
||||
alias
|
||||
"_integers"
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
object_ptr: POINTER
|
||||
object_ptr: POINTER
|
||||
|
||||
end -- class INTARRAY
|
||||
</code>
|
||||
|
||||
@@ -30,7 +30,7 @@ extern size_t one_param_return(FILE *f);</code>
|
||||
|
||||
Here is the corresponding Eiffel code:
|
||||
<code>
|
||||
c_no_param is
|
||||
c_no_param
|
||||
-- Encapsulation of a C routine with no parameter.
|
||||
external
|
||||
"C | %"my_header.h%""
|
||||
@@ -38,7 +38,7 @@ Here is the corresponding Eiffel code:
|
||||
"no_param"
|
||||
end
|
||||
|
||||
c_one_param (i: INTEGER) is
|
||||
c_one_param (i: INTEGER)
|
||||
-- Encapsulation of a C routine with one parameter.
|
||||
external
|
||||
"C (int) | %"my_header.h%""
|
||||
@@ -46,7 +46,7 @@ Here is the corresponding Eiffel code:
|
||||
"one_param"
|
||||
end
|
||||
|
||||
c_no_param_return: INTEGER is
|
||||
c_no_param_return: INTEGER
|
||||
-- Encapsulation of a C routine with no parameter
|
||||
-- returning an INTEGER
|
||||
external
|
||||
@@ -55,7 +55,7 @@ Here is the corresponding Eiffel code:
|
||||
"no_param_return"
|
||||
end
|
||||
|
||||
c_one_param_return (p: POINTER): INTEGER is
|
||||
c_one_param_return (p: POINTER): INTEGER
|
||||
-- Encapsulation of a C routine with one parameter
|
||||
-- returning an INTEGER
|
||||
external
|
||||
@@ -82,7 +82,7 @@ Then, the corresponding Eiffel code will look like:
|
||||
|
||||
|
||||
<code>
|
||||
menu_id: INTEGER is
|
||||
menu_id: INTEGER
|
||||
-- `ID_MENU' C encapsulation.
|
||||
external
|
||||
"C [macro %"my_header.h%"] : EIF_INTEGER"
|
||||
@@ -90,7 +90,7 @@ Then, the corresponding Eiffel code will look like:
|
||||
"ID_MENU"
|
||||
end
|
||||
|
||||
menu_id_character: CHARACTER is
|
||||
menu_id_character: CHARACTER
|
||||
-- `ID_MENU_CHARACTER' C encapsulation.
|
||||
external
|
||||
"C [macro %"my_header.h%"] : EIF_CHARACTER"
|
||||
@@ -98,7 +98,7 @@ Then, the corresponding Eiffel code will look like:
|
||||
"ID_MENU_CHARACTER"
|
||||
end
|
||||
|
||||
i_th (p: POINTER; i: INTEGER): INTEGER is
|
||||
i_th (p: POINTER; i: INTEGER): INTEGER
|
||||
-- Access the `i'-th element of `p', array of C EIF_INTEGER.
|
||||
external
|
||||
"C [macro %"my_header.h%"] (EIF_INTEGER *, EIF_INTEGER): EIF_INTEGER"
|
||||
@@ -125,7 +125,7 @@ typdef struct point {
|
||||
|
||||
Then, the corresponding Eiffel code will look like:
|
||||
<code>
|
||||
x (p: POINTER): INTEGER is
|
||||
x (p: POINTER): INTEGER
|
||||
-- Access field x of struct pointed by `p'.
|
||||
external
|
||||
"C [struct %"my_header.h%"] (Point): EIF_INTEGER"
|
||||
@@ -133,7 +133,7 @@ Then, the corresponding Eiffel code will look like:
|
||||
"x"
|
||||
end
|
||||
|
||||
y (p: POINTER): INTEGER is
|
||||
y (p: POINTER): INTEGER
|
||||
-- Access field y of struct pointed by `p'.
|
||||
external
|
||||
"C [struct %"my_header.h%"] (Point): EIF_INTEGER"
|
||||
@@ -141,7 +141,7 @@ Then, the corresponding Eiffel code will look like:
|
||||
"y"
|
||||
end
|
||||
|
||||
set_x (p: POINTER; v: INTEGER) is
|
||||
set_x (p: POINTER; v: INTEGER)
|
||||
-- Set field x of struct pointed by `p'.
|
||||
external
|
||||
"C [struct %"my_header.h%"] (Point, int)"
|
||||
@@ -149,7 +149,7 @@ Then, the corresponding Eiffel code will look like:
|
||||
"x"
|
||||
end
|
||||
|
||||
set_y (p: POINTER: v: INTEGER) is
|
||||
set_y (p: POINTER: v: INTEGER)
|
||||
-- Set field y of struct pointed by `p' with `v'.
|
||||
external
|
||||
"C [struct %"my_header.h%"] (Point, int)"
|
||||
@@ -171,13 +171,13 @@ Therefore if you want to call an external routine defined in a DLL supposed to b
|
||||
|
||||
|
||||
<code>
|
||||
my_cdecl_routine (a: INTEGER): POINTER is
|
||||
my_cdecl_routine (a: INTEGER): POINTER
|
||||
-- Encapsulation of a dll function with the `_cdecl' call mechanism.
|
||||
external
|
||||
"C [dll32 %"my_dll.dll%"] (int): EIF_POINTER"
|
||||
end
|
||||
|
||||
my_stdcall_routine (a: INTEGER): POINTER is
|
||||
my_stdcall_routine (a: INTEGER): POINTER
|
||||
-- Encapsulation of a dll function with the `_stdcall' call mechanism.
|
||||
external
|
||||
"C [dllwin32 %"my_dll.dll%"] (int): EIF_POINTER"
|
||||
@@ -207,7 +207,7 @@ In WEL, the encapsulation is written as:
|
||||
|
||||
|
||||
<code>
|
||||
cwin_send_message (hwnd: POINTER; msg, wparam, param: INTEGER) is
|
||||
cwin_send_message (hwnd: POINTER; msg, wparam, param: INTEGER)
|
||||
-- SDK SendMessage (without the result)
|
||||
external
|
||||
"C [macro %"wel.h%"] (HWND, UINT, WPARAM, LPARAM)"
|
||||
|
||||
@@ -43,58 +43,59 @@ Value of `my_integer' after call to `my_method' is 2
|
||||
===Code description===
|
||||
<code>(Eiffel Code)
|
||||
|
||||
class
|
||||
EIFFEL_TO_JAVA
|
||||
inherit
|
||||
SHARED_JNI_ENVIRONMENT
|
||||
class
|
||||
EIFFEL_TO_JAVA
|
||||
inherit
|
||||
SHARED_JNI_ENVIRONMENT
|
||||
|
||||
create
|
||||
make
|
||||
make
|
||||
|
||||
feature -- Creation
|
||||
feature -- Creation
|
||||
|
||||
make is
|
||||
local
|
||||
class_test: JAVA_CLASS
|
||||
instance_of_class_test: JAVA_OBJECT
|
||||
fid: POINTER
|
||||
value: INTEGER
|
||||
j_args: JAVA_ARGS
|
||||
do
|
||||
--| Creation of the Java object
|
||||
class_test := jni.find_class ("test")
|
||||
create instance_of_class_test.create_instance (class_test, "()V", Void)
|
||||
make
|
||||
local
|
||||
class_test: JAVA_CLASS
|
||||
instance_of_class_test: JAVA_OBJECT
|
||||
fid: POINTER
|
||||
value: INTEGER
|
||||
j_args: JAVA_ARGS
|
||||
do
|
||||
--| Creation of the Java object
|
||||
class_test := jni.find_class ("test")
|
||||
create instance_of_class_test.create_instance (class_test, "()V", Void)
|
||||
|
||||
--| Access to a public attribute
|
||||
fid := instance_of_class_test.field_id ("my_integer", "I")
|
||||
--| Access to a public attribute
|
||||
fid := instance_of_class_test.field_id ("my_integer", "I")
|
||||
|
||||
-- 'fid' contains the id of the field 'my_integer'
|
||||
-- 'value' contains the value of the field referenced
|
||||
-- by 'fid'
|
||||
-- 'fid' contains the id of the field 'my_integer'
|
||||
-- 'value' contains the value of the field referenced
|
||||
-- by 'fid'
|
||||
|
||||
value := instance_of_class_test.integer_attribute (fid)
|
||||
value := instance_of_class_test.integer_attribute (fid)
|
||||
|
||||
--| Access to a static attribute using directly the JAVA_CLASS
|
||||
fid := class_test.field_id ("my_static_integer", "I")
|
||||
value := class_test.integer_attribute (fid) ...
|
||||
|
||||
--| Access to a static attribute using the attribute 'jclass'
|
||||
fid := instance_of_class_test.jclass.field_id ("my_static_integer", "I")
|
||||
value := instance_of_class_test.jclass.integer_attribute (fid)
|
||||
|
||||
--| Access to the method 'my_method'
|
||||
-- Get the id of 'my_method'
|
||||
fid := instance_of_class_test.method_id ("my_method", "(ILjava/lang/String;)V")
|
||||
--| Access to a static attribute using directly the JAVA_CLASS
|
||||
fid := class_test.field_id ("my_static_integer", "I")
|
||||
value := class_test.integer_attribute (fid)
|
||||
|
||||
-- Create the set of arguments for 'my_method'
|
||||
create j_args.make(2)
|
||||
j_args.push_int (2)
|
||||
j_args.push_string("String test")
|
||||
|
||||
-- Create the set of arguments for 'my_method'
|
||||
-- Call to the void method referenced by 'fid'
|
||||
instance_of_class_test.void_method (fid, j_args)
|
||||
end -- make
|
||||
--| Access to a static attribute using the attribute 'jclass'
|
||||
fid := instance_of_class_test.jclass.field_id ("my_static_integer", "I")
|
||||
value := instance_of_class_test.jclass.integer_attribute (fid)
|
||||
|
||||
--| Access to the method 'my_method'
|
||||
-- Get the id of 'my_method'
|
||||
fid := instance_of_class_test.method_id ("my_method", "(ILjava/lang/String;)V")
|
||||
|
||||
-- Create the set of arguments for 'my_method'
|
||||
create j_args.make(2)
|
||||
j_args.push_int (2)
|
||||
j_args.push_string("String test")
|
||||
|
||||
-- Create the set of arguments for 'my_method'
|
||||
-- Call to the void method referenced by 'fid'
|
||||
instance_of_class_test.void_method (fid, j_args)
|
||||
end -- make
|
||||
|
||||
end -- class EIFFEL_TO_JAVA</code>
|
||||
|
||||
|
||||
@@ -10,14 +10,15 @@ The Java interface allows you to call Java routines or attributes from your Eiff
|
||||
===Requirements===
|
||||
* JDK 1.1.8 or newer should be correctly set up (download it at [http://java.sun.com/javase/downloads/index.jsp http://java.sun.com/javase/downloads/index.jsp] )
|
||||
* The environment variable CLASSPATH should defined (check with the JDK documentation on how to do so) and that it contains the Java classes you want to access.
|
||||
* The environment variables should be setup correctly. See $ISE_EIFFEL\library\Eiffel2Java\README.txt for information how to do this..
|
||||
* The environment variables should be setup correctly. See $ISE_EIFFEL\library\Eiffel2Java\README.txt for information how to do this.
|
||||
|
||||
===Borland users===
|
||||
|
||||
On Windows, the JDK includes a set of C libraries which have been compiled for the Microsoft C compiler. Before being able to use the JDK from Eiffel you need to perform the following operation:
|
||||
# In $JDK_HOME\lib, rename javai.lib into javai.lib.microsoft
|
||||
# From the DOS command prompt and in the directory $JDK_HOME\lib, launch the following command <br/>
|
||||
<code>%ISE_EIFFEL%\bcc55\bin\implib javai.lib..\bin\javai.dll</code>
|
||||
<code lang=text>
|
||||
%ISE_EIFFEL%\bcc55\bin\implib javai.lib..\bin\javai.dll</code>
|
||||
|
||||
|
||||
===Limitations===
|
||||
@@ -143,17 +144,21 @@ When you want to call a Java method or access a field, you need to specify its s
|
||||
|}
|
||||
|
||||
The signature for a Java class has the following form:
|
||||
<code>L fully-qualified-class;</code>
|
||||
<code lang=text>
|
||||
L fully-qualified-class;</code>
|
||||
|
||||
For example, class String:
|
||||
<code>Ljava/lang/String;</code>
|
||||
<code lang=text>
|
||||
Ljava/lang/String;</code>
|
||||
|
||||
|
||||
The signature for a method has the following form:
|
||||
<code>(arguments-types) returned-types</code>
|
||||
<code lang=text>
|
||||
(arguments-types) returned-types</code>
|
||||
|
||||
For example, the signature of a method that takes as arguments an integer and a string and return void is:
|
||||
<code>(ILjava/lang/String;)V</code>
|
||||
<code lang=text>
|
||||
(ILjava/lang/String;)V</code>
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user