Created 18.01 branch of the documentation.

git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@1942 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
eiffel-org
2018-02-08 15:00:31 +00:00
parent 265a446dab
commit b5d5c80911
2923 changed files with 61520 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
[[Property:title|Eiffel "external" mechanism]]
[[Property:weight|0]]
[[Property:uuid|b6ea568d-a9d3-3220-7957-d9c81620e885]]
{{UnderConstruction}}
The Eiffel mechanism for interfacing with other languages, as defined by the [[ECMA Standard 367|Eiffel standard (8.31)]] uses a syntax for '''external''' features, that is, features that are in languages or libraries external to Eiffel.
Additionally, there is a notion of such external languages being either '''registered''' or '''unregistered'''. A language is registered if every Eiffel implementation must support the external interface to this language as defined by the standard. So the names of all registered languages appear in the Eiffel standard. And the details of the specific external mechanisms for those languages also appear in the standard. Registered languages included in the June 2006 edition of the standard are '''"C"''', '''"C++"''', and '''"dll"'''.
The case of unregistered languages is simply that there is no guarantee that such a language is supported by any particular Eiffel compiler. So, a the name of an unregistered language might appear as '''"Cobol"''' or '''"Ada"'''. These names may be meaningful to particular Eiffel compilers, but from the standpoint of the standard they are arbitrary manifest strings.

View File

@@ -0,0 +1,123 @@
[[Property:title|Interfacing with C and C++]]
[[Property:weight|0]]
[[Property:uuid|dcc4e216-307b-46ec-1bc1-a15da8b99469]]
{{UnderConstruction}}
Interfacing with C and C++ are similar enough that both can be covered together. There are two basic mechanisms available. The first and simpler of the two uses an existing routine and is available only to C externals. Using this approach you simply specify the '''signature''' of an existing C function along with where the function can be found. The second mechanism allows you to write C or C++ code inline. The second option is always recognizable by the presence of the word "'''inline'''" in the external specification. Again, the '''inline''' option is the only one allowed for C++ externals.
==Using an existing C function==
Here is an example of an external targeting an existing C function. In this case it's the <code>floor</code> function from the C library.
<code>
floor (v: DOUBLE): DOUBLE
-- Floor of `v'
external
"C signature (double): double use <math.h>"
end
</code>
The Eiffel external function <code>floor</code> now gives Eiffel code access to the C library function of the same name.
Here <code>external</code> is an Eiffel keyword that introduces the external specification that appears in the quoted string that follows. (The quoted string is actually an Eiffel [[ET: Other mechanisms|manifest string]], so it could actually be a simple quoted string or a [[ET: Other mechanisms|verbatim string]].) Within the quoted string we find first the registered language designator, in this case "C", followed by the function's signature, followed by the location in which the C function can be found. The terms "signature" and "use" within the quoted string are technically not Eiffel language keywords, but are keywords used in the specification of externals. There is one other similar keyword "inline" which can be used, but we will address it later.
The "signature" consists of the types of the arguments to C function as well as the function's return type. The argument types are separated by commas in a list enclosed in parentheses. A colon precedes the function type. In cases in which the target function takes no arguments, it is not necessary to include a set of empty parentheses in the signature. However, for compatibility purposes, the empty parentheses are allowed.
The "use" part denotes provides a file name or list of file names. File names can be either "user" file names or "system" file names. In the case of our example, a system file name "<code><math.h></code>" is used. System files are those that should be found by the system with no additional information. System file names are enclosed in angle brackets. User file names are included in a quoted string. User file names will be passed as written to the operating system. Remember that when coding a user file name, that because it already occurs within a quoted string, you must use the percent sign to code the quotation marks inside a quoted string, for example:
<code>
"C signature (double): double use %"my_c_header.h%""
</code>
Alternatively, you could code the external as a verbatim string. This would make the percent signs unnecessary.
There's one more thing to note about using existing C functions. In the <code>floor</code> example above, the Eiffel function has the same name as the C function it targets. But that may not always be the case. It's possible that the C function name might conflict with a name already established in your class, or might conflict with Eiffel naming conventions. Suppose you wanted to call the Eiffel routine <code>my_floor</code> instead of <code>floor</code>. You could use the <code>alias</code> part of the external specification to state that the actual C function name differs from the Eiffel name, as shown below.
<code>
my_floor (v: DOUBLE): DOUBLE
-- Floor of `v'
external
"C signature (double): double use <math.h>"
alias
"floor"
end
</code>
==Inline externals==
In addition to using an existing C function, you can, for both C and C++, create an '''inline''' external. The idea here is that you write the necessary C or C++ language within the definition of the external. In the case of inline externals the <code>alias</code> part is used to contain the inline code rather than a function name. Your inline C and C++ code can access the arguments of the external feature. Let's look at <code>my_floor</code> written as an inline external:
<code>
my_floor (v: DOUBLE): DOUBLE
-- Floor of `v'
external
"C inline use <math.h>"
alias
"return floor($v)"
end
</code>
In the <code>alias</code> part you see a line of C code calling the library function <code>floor</code> and returning the result. The argument to the call to <code>floor</code> needs to be the argument to the Eiffel function <code>my_floor</code>. To do this in the inline C code, the dollar sign ('$') precedes the argument name "v". So, the convention in inline externals is to use the dollar sign in C or C++ code to reference an argument of the Eiffel function.
The example below is a C++ example that involves more complex processing in the <code>alias</code> part.
<code>
c_height (a_framework: POINTER): INTEGER
-- Get ribbon height
require
a_framework_exists: a_framework /= default_pointer
external
"C++ inline use <common.h>"
alias
"{
UINT32 val;
HRESULT hr = S_OK;
IUIRibbon* pRibbon = NULL;
if (SUCCEEDED(((IUIFramework *) $a_framework)->GetView(0, IID_IUIRIBBON, (void **) &pRibbon))) {
hr = pRibbon->GetHeight(&val);
pRibbon->Release();
}
return (EIF_INTEGER) val;
}"
end
</code>
==Rules for C and C++ externals==
===C external validity===
A C external is valid if it satisfies the following conditions:
# It specifies either an external signature or an inline routine.
# If it specifies an inline routine, then
## The C text of the routine follows the <code>alias</code> keyword.
## For any occurrence, within the C text, of an identifier following a dollar sign ('$'), the identifier must be the name of an argument of the external routine.
===C++ external validity===
A C++ external is valid if it satisfies the following conditions:
# It specifies an inline routine with the C++ text of the routine occurring after the <code>alias</code> keyword.
# For any occurrence, within the C++ text, of an identifier following a dollar sign ('$'), the identifier must be the name of an argument of the external routine.
===External file name validity===
An external file name appearing after the "use" is valid if it satisfies the following conditions:
# It denotes a file when interpreted according to the conventions of the underlying operating system.
# The file is accessible for reading.
# The file contains content valid in the target language.
The first condition means that user file names must conform to the path and file names of the target environment. Such file names will be passed on to the operating system as they appear. And for system file names, those enclosed in angle brackets, this means that they must be found where the operating system would expect such system files to reside.
Some parts of the validity of external file names may not be able to be determined by an Eiffel compiler and thus ultimately depend upon the evaluation of an external compiler. For example, the Eiffel compiler might not be able to determine whether a particular C file contains valid content.

View File

@@ -0,0 +1,29 @@
[[Property:title|Interfacing with DLLs]]
[[Property:weight|0]]
[[Property:uuid|4ad177dd-13ec-c237-99b3-efc9851995a5]]
Using EiffelStudio, there are two different ways to call C routines exported in DLLs. This is because on the Windows platform, there are two frequently-used calling conventions for C routines found in DLLs:
* _cdecl: referred to as the standard calling convention
* __stdcall referred to as the Pascal calling convention
Calling conventions define 1) how arguments are placed on the stack, and 2) which entity (the caller, or the callee) is responsible for returning the call stack to its previous state when the routine has completed. These two methods are NOT compatible. Therefore if you have a routine in a DLL you wish to call, one of the first things to find out about it is which calling convention it expects. DLL routines that use the `_cdecl` calling convention require the use of the '''dll32''' sub-language option. For `__stdcall`, use the '''dllwin32''' sub-language option. Here is an example:
<code>
my_cdecl_routine (a: INTEGER): POINTER
-- Encapsulation of a dll function with the `_cdecl' call mechanism.
external
"C [dll32 %"my_cdecl_dll.dll%"] (int): EIF_POINTER"
end
my_stdcall_routine (a: INTEGER): POINTER
-- Encapsulation of a dll function with the `_stdcall' call mechanism.
external
"C [dllwin32 %"my_stdcall_dll.dll%"] (int): EIF_POINTER"
end
</code>
{{note|Most OS services provided by the Win32 API use the __stdcall calling convention.}}
{{warning|Getting '''dll32''' and '''dllwin32''' reversed will cause your application's call stack to be corrupted. This will cause your application to malfunction, can cause it to crash, and can potentially crash your whole system. So getting this right is crucial to smooth implementation of external DLL calls. For more information please consult your C compiler documentation.}}

View File

@@ -0,0 +1,302 @@
[[Property:title|C++ Externals]]
[[Property:weight|2]]
[[Property:uuid|e74e2661-5d7f-2f08-5279-1c24fd16a532]]
==Introduction==
Before making C++ calls in EiffelStudio, you may want to learn the basics of making [[C externals|C calls]] , since these basics are not repeated here but they might be useful for C++ users as well and are necessary to fully benefit from this document.
==Overview==
Eiffel software must interact with software written in other languages. In this document you will learn about how to incorporate C++ classes in your Eiffel software.
The C++/Eiffel interface offers the following mechanisms:
* You can create instances of C++ classes from Eiffel, using the C++ "constructor" of your choice.
* You can apply to these objects all the corresponding operations from the C++ class: executing functions ("methods"), accessing data members, executing destructors.
* On Windows, you can use the Legacy++ tool to produce an Eiffel "wrapper class" encapsulating all the features of a C++ class, so that the result will look to the rest of the Eiffel software as if it had been written in Eiffel.
The discussion concentrates on using C++ software from Eiffel. In the other direction, you can use [[CECIL|the Cecil library (C-Eiffel Call-In Library)]] .
==Syntax specification==
In the following specification, the syntax for External and External_name is retained unchanged from ''Eiffel: The Language'', where Language_name is defined simply as Manifest_string; the rest covers the additional facilities.
<code>
External == external Language_name [External_name]
Language_name ==
'"'
Basic_language_name
[Special_external_declaration]
[Signature]
[Include_files]
'"'
Basic_language_name == "C" | "C++"
Special_external_declaration == "[" Special_feature "]"
Special_feature == Special_C_feature | Special_C++_feature
Special_C_feature == -- .... See appendix E of Eiffel: The Language...
Special_C++_feature ==
Member_function_call|
Static_function_call |
Object_creation |
Object_deletion |
Data_member_access |
Member_function_call == C++_Class
C++_Class == Class_name File_name
Class_name == Identifier
Static_function_call == static C++_Class
Object_creation == new C++_Class
Object_deletion == delete C++_Class
Data_member_access == data_member C++_Class
-- The remaining elements are repeated
-- from the C interface specification (page 291 in Eiffel: The Environment).
File_name == User_file_name | System_file_name
User_file_name == '%"' Manifest string '%"'
System_file_name == "<" Manifest_string ">"
Signature == "(" Type_list ")" [Result_type]
Type_list == {Type "," ...}
Result_type == ":" Type
Include_files == "|" File_list
File_list == {File_name "," ...}
External_name == alias Manifest_string
</code>
As with the C extensions of the previous appendix, the syntax description conventions are those of ''Eiffel: The Language''. == means "is defined as". The vertical bar | separates alternative choices, such as the three possibilities for Special_feature. The brackets [...] enclose optional components; for example a Language_name is made of required quotes, a required Basic_language_name and three further components, any or all of which may be absent. The notation {Element Separator ...} means: 0 or more occurrences ("specimens") of Element separated, if more than one, by Separator.
Several of the symbols of the syntax notation, such as the brackets or the vertical bar, also appear in the language; to avoid any confusion they are given in double quotes. For example the specification for Include_files begins with "|" to indicate that an Include_files part starts with a vertical bar. Single quotes may be used instead of double quotes when one of the quoted characters is itself a double quote; for example '%"' appearing in the production for User_file_name denotes the percent character followed by the double quote character. Special words such as '''static''' in bold italics stand for themselves, unquoted.
==Available possibilities==
===Processing C++ features===
A Special_C++_feature, if present, indicates one of the following, all illustrated by examples in the next sections:
* If the special feature's declaration simply starts with a C++ class name, followed by the associated file name, it indicates that the Eiffel feature will call a C++ member function (also known as a "method") from that class. The name of the member function is by default the same as the name of the Eiffel feature; as usual, you can specify a different name through the alias clause of the external declaration.
* If the declaration starts with <code>static</code>, it indicates a call to a C++ static function.
* If the declaration starts with <code>new</code>, it indicates a call to one of the constructors in the C++ class, which will create a new instance of that class and apply to it the corresponding constructor function.
* If the declaration starts with <code>delete</code>, it indicates a call to a destructor from the C++ class. In this case the Eiffel class may inherit [[ref:libraries/base/reference/memory_chart|MEMORY]] and redefine the dispose procedure to execute the destructor operations whenever the Eiffel objects are garbage-collected.
* If the declaration starts with <code>data_member</code>, it indicates access to a data member (attribute in Eiffel terminology) from the C++ class.
The rest of the possible components are the same as in the C interface: Signature to specify types for arguments and results; possible Include file.
===Extra argument===
For a non-static C++ member function or destructor, the corresponding Eiffel feature should include an extra argument of type POINTER, at the first position. This argument represents the C++ object to which the function will be applied.
For example, a C++ function
<code>void add(int new_int);</code>
should have the Eiffel counterpart
<code>
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)
-- 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.
There is no need for an extra argument in the case of static member functions and constructors.
==Wrapping C++ classes: Legacy++==
Before taking a look at examples of the various facilities mentioned, it is useful to consider the tool that will help you, in many cases, avoid worrying about their details.
===The role of Legacy++===
Often you will want to provide an Eiffel encapsulation of all the facilities -- member functions, static functions, constructors, destructors, data members -- of a C++ class. This means producing an Eiffel class that will provide an Eiffel feature for each one of these C++ facilities, using external declarations based on the mechanisms listed in the preceding section.
Rather than writing these external declarations and the class structure manually, you can use the Legacy++ tool to produce the Eiffel class automatically from the C++ class.
===Calling Legacy++===
Legacy++ is called with an argument denoting a ''.h'' file that must contain C++ code: one or more classes and structure declarations. It will translate these declarations into Eiffel wrapper classes. Legacy++ is only available on Windows. It is located in the $ISE_EIFFEL\studio\spec\windows\bin directory, under the name legacy.exe.
The following options are available:
* '''-E''': apply the C preprocessor to the file, so that it will process #include, #define, #ifdef and other preprocessor directives. This is in fact the default, so that you do not need to specify -E explicitly (see next option).
* '''-NE''': do not apply the C preprocessor to the file.
* '''-p''' ''directories'': use ''directories'' as include path.
* '''-c''' ''compiler'': use ''compiler'' as the C++ compiler.
* '''-g''': treat the C++ code as being intended for the GNU C++ compiler.
===Result of applying Legacy++===
Running Legacy++ on a C++ file will produce the corresponding Eiffel classes. Legacy++ processes not only C++ classes but also C++ "structs"; in both cases it will generate an Eiffel class.
Legacy++ knows about default specifiers: public for structs, private for classes.
Legacy++ will generate Eiffel features for member functions (static or not).
It will also handle any constructors and destructors given in the C++ code, yielding the corresponding Eiffel creation procedures. If there is no explicit constructor, it will produce a creation procedure with no arguments and an empty body.
For any non-static member function or destructor, Legacy++ will generate a secret feature with an extra argument representing the object, as explained in the preceding section in this page. It will also produce a public feature with the same number of arguments as the C++ function, relying on a call to the secret feature, as illustrated for <eiffel>add </eiffel>and <eiffel>cpp_add</eiffel> above.
The char* type is translated into <eiffel>STRING</eiffel>. Pointer types, as well as reference types corresponding to classes and types that Legacy++ has processed, will be translated into <eiffel>POINTER</eiffel>. Other types will yield the type <eiffel>UNRESOLVED_TYPE</eiffel>.
===Legacy++ limitations===
It is up to you to supply Eiffel equivalents of all the needed types. If Legacy++ encounters the name of a C++ class or type that it does not know -- i.e. it is neither a predefined type nor a previously translated class -- it will use the Eiffel type name <eiffel>UNRESOLVED_TYPE</eiffel>. If you do not change that type in the generated class, the Eiffel compiler will produce an error (unknown class) at degree 5.
Legacy++ does not handle inline function declarations.
Legacy++ does not handle C++ templates.
Legacy++ makes no effort to understand the C++ inheritance structure.
More generally, given the differences in the semantic models of C++ and Eiffel, Legacy++ can only perform the basic Eiffel wrapping of a C++ class, rather than a full translation. You should always inspect the result and be prepared to adapt it manually.
Legacy++'s contribution is to take care of the bulk of the work, in particular the tedious and repetitive parts. The final details are left to the Eiffel software developer.
Legacy++ is only supported on the windows platform.
==Example==
Consider the following C++ class, which has an example of every kind of facility that one may wish to access from the Eiffel side:
<code lang="cpp">
class IntArray {
public:
IntArray(int size);
~IntArray();
void output();
void add(int new_int);
static char * type();
protected:
int *_integers;
};
</code>
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>
note
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
inherit
MEMORY
redefine
dispose
end
create
make
feature -- Initialization
make (size: INTEGER)
-- Create Eiffel and C++ objects.
do
object_ptr := cpp_new (size)
end
feature-- Removal
dispose
-- Delete C++ object.
do
cpp_delete (object_ptr)
end
feature
output
-- Call C++ counterpart.
do
cpp_output (object_ptr)
end
add (new_int: INTEGER)
-- Call C++ counterpart.
do
cpp_add (object_ptr, new_int)
end
feature {INTARRAY}
underscore_integers: POINTER
-- Value of corresponding C++ data member.
do
Result := underscore_integers (object_ptr)
end
feature {NONE} -- Externals
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)
-- Call C++ destructor on C++ object.
external
"C++ [delete IntArray %"INTARRAY.H%"] ()"
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)
-- Call C++ member function.
external
"C++ [IntArray %"INTARRAY.H%"] (EIF_INTEGER)"
alias
"add"
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
end -- class INTARRAY
</code>

View File

@@ -0,0 +1,224 @@
[[Property:title|C externals]]
[[Property:weight|1]]
[[Property:uuid|f6a5ce2d-882b-27a2-ad6e-2e4c36027528]]
==General consideration==
As Eiffel Software's technology relies heavily on the use of a C/C++ ANSI compiler, you have to be sure to always put the correct signature of an external C/C++ routine. If it was not the case, the C compilation of your system could fail. Most of the time a C compiler is more comprehensive than a C++ compiler and most type errors won't cause you any harm, but C++ compilers are not as lax as C compilers and they will mostly generate errors.
The sections concerning [[#macros|Macros]] and [[#structs|Structs]] are also available for C++ if the macro or the struct is defined in a C++ header file.
<span id="C"></span>
==C routines==
You can encapsulate routines that are defined in a C header file. We will take some examples and will show you how to write wrappers in Eiffel.
If in a header file called `my_header.h`, you have the following declaration:
<code lang="c">
/* Routine with no parameter */
extern void no_param(void);
/* Routine with one parameter */
extern void one_param(int j);
/* Routine returning a value with no parameter */
extern size_t no_param_return(void);
/* Routine returning a value with one parameter */
extern size_t one_param_return(FILE *f);</code>
Here is the corresponding Eiffel code:
<code>
c_no_param
-- Encapsulation of a C routine with no parameter.
external
"C | %"my_header.h%""
alias
"no_param"
end
c_one_param (i: INTEGER)
-- Encapsulation of a C routine with one parameter.
external
"C (int) | %"my_header.h%""
alias
"one_param"
end
c_no_param_return: INTEGER
-- Encapsulation of a C routine with no parameter
-- returning an INTEGER
external
"C (): EIF_INTEGER| %"my_header.h%""
alias
"no_param_return"
end
c_one_param_return (p: POINTER): INTEGER
-- Encapsulation of a C routine with one parameter
-- returning an INTEGER
external
"C (FILE *): EIF_INTEGER| %"my_header.h%""
alias
"one_param_return"
end</code>
<span id="macros"></span>
==Macros==
If in a header file called `my_header.h`, you have the following declaration:
<code lang="c">
/* Predefined constants */
#define ID_MENU 128
#define ID_MENU_CHARACTER 'c'
/* Access the 'i'-th element of 'a' where 'a' * is an array of EIF_INTEGER */
#define i_th(a,i)((a) + (i)*sizeof(EIF_INTEGER))</code>
Then, the corresponding Eiffel code will look like:
<code>
menu_id: INTEGER
-- `ID_MENU' C encapsulation.
external
"C [macro %"my_header.h%"] : EIF_INTEGER"
alias
"ID_MENU"
end
menu_id_character: CHARACTER
-- `ID_MENU_CHARACTER' C encapsulation.
external
"C [macro %"my_header.h%"] : EIF_CHARACTER"
alias
"ID_MENU_CHARACTER"
end
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"
alias
"i_th"
end</code>
<span id="structs"></span>
==Structs==
The struct encapsulation enables you to wrap C/C++ structures easily without having to write any additional code in a C header file as it was the case until Eiffel Software introduced this new keyword in the external specification with the 4.5 release of the Eiffel Software environment. With the struct encapsulation you can set and retrieve the value of a certain field of a struct.
If in a header file called `my_header.h`, you have the following declaration of the `Point` structure whose `x` and `y` fields we want to access and set:
<code lang="c">
/* Definition of `Point' */
typdef struct point {
int x;
int y;
} Point;</code>
Then, the corresponding Eiffel code will look like:
<code>
x (p: POINTER): INTEGER
-- Access field x of struct pointed by `p'.
external
"C [struct %"my_header.h%"] (Point): EIF_INTEGER"
alias
"x"
end
y (p: POINTER): INTEGER
-- Access field y of struct pointed by `p'.
external
"C [struct %"my_header.h%"] (Point): EIF_INTEGER"
alias
"y"
end
set_x (p: POINTER; v: INTEGER)
-- Set field x of struct pointed by `p'.
external
"C [struct %"my_header.h%"] (Point, int)"
alias
"x"
end
set_y (p: POINTER: v: INTEGER)
-- Set field y of struct pointed by `p' with `v'.
external
"C [struct %"my_header.h%"] (Point, int)"
alias
"y"
end</code>
<span id="windows"></span>
==Windows externals==
===DLLs===
With EiffelStudio you now have two different ways to call C routines exported in a DLL. Why two, because Windows provides two ways to call a C routine in a DLL:
* _cdecl: referred to as the standard way
* __stdcall referred to as the Pascal way
Therefore if you want to call an external routine defined in a DLL supposed to be called using the `_cdecl` method, you have to use the '''dll32''' sub-language option. For `__stdcall` you need to use the '''dllwin32''' sub-language option. Here is an example:
<code>
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
-- Encapsulation of a dll function with the `_stdcall' call mechanism.
external
"C [dllwin32 %"my_dll.dll%"] (int): EIF_POINTER"
end</code>
{{warning|Using '''dll32''' in cases calling for '''dllwin32''' and vice versa will cause your system to crash, because the C call stack will be corrupted. For more information please read your C compiler documentation. }}
===Windows API===
As described in the previous section concerning routines exported in a DLL, the Windows API is using the `__stdcall` convention. As a consequence, you cannot use the standard external mechanism to wrap them because it is using the `_cdecl` convention. However, you can easily wrap those function by using the '''macro''' sub-language.
Here is an example that has been taken from WEL, the Windows Eiffel Library, to encapsulate the Windows `SendMessage` function:
Windows defined SendMessage as:
<code lang="cpp">LRESULT SendMessage(
HWND hWnd, // handle to destination window
UINT Msg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);</code>
In WEL, the encapsulation is written as:
<code>
cwin_send_message (hwnd: POINTER; msg, wparam, param: INTEGER)
-- SDK SendMessage (without the result)
external
"C [macro %"wel.h%"] (HWND, UINT, WPARAM, LPARAM)"
alias
"SendMessage"
end</code>
{{seealso|<br/>
[[C++ Externals|C++ externals]] }}

View File

@@ -0,0 +1,11 @@
[[Property:title|Obsolete "external" interfaces]]
[[Property:weight|0]]
[[Property:uuid|1b72d727-711e-2cab-8010-d62842e5230a]]
{{UnderConstruction}}
The interface mechanisms for C and C++ on the following pages are now been superseded in favor of the mechanism described in the Eiffel standard.