Though not specifically answering your question, you should consider defining, in your Eiffel code, some handy C structs the help with some of the more complex interactions.
I have a master class (ael_struct) that makes it easy to create others. The Eiffel class representing your struct needs a size (for memory allocation) and needs features that represent the members of the struct. This doesn't eliminate the need to map Eiffel to C, but it does help organize things a bit better.
R
Here's the text of the class (de-formatted, thanks to my email client)
>>>>>
note
description: "{
A generic wrapper for C structs
}"
system: "Part of the Amalasoft Eiffel Library."
source: "Amalasoft Corporation"
license: "Eiffel Forum V2"
copyright: "Copyright (c) 1995-2013 Amalasoft Corporation. All Rights Reserved"
date: "See comments at bottom of class."
revision: "See comments at bottom of class."
howto: "See comments at bottom of class."
history: "See comments at bottom of class."
class AEL_STRUCT
inherit
MEMORY
redefine
default_create, dispose
end
create
default_create, make, make_from_c
--|========================================================================
feature {NONE} -- Creation and initialization
--|========================================================================
default_create
-- Create Current in its default state
-- N.B. allocates memory from heap on creation
-- Do NOT free explicitly when out of scope!!!
do
allocate_structure_memory
ensure then
valid: is_valid_address (address)
end
make
-- Create Current with newly allocated memory
-- Do NOT free when out of scope!!!
do
default_create
ensure
valid: is_valid_address (address)
end
--|------------------------------------------------------------------------
make_from_c (v: POINTER)
-- Create Current from C struct at address 'v'
-- Do NOT free when out of scope!!!
require
valid_ptr: v /= Default_pointer
do
address := v
ensure
valid: is_valid_address (address)
end
--|------------------------------------------------------------------------
make_disposable
-- Create Current with newly allocated memory
-- Ensure the allocated memory is freed on dispose
do
ok_to_free_address := True
make
ensure
valid: is_valid_address (address)
end
--|------------------------------------------------------------------------
make_disposable_from_c (v: POINTER)
-- Create Current with address 'v', presumably allocated
-- from C, but ..
-- Ensure the allocated memory is freed on dispose
require
valid_ptr: v /= Default_pointer
do
ok_to_free_address := True
make_from_c (v)
ensure
valid: is_valid_address (address)
end
--|========================================================================
feature -- Status
--|========================================================================
address: POINTER
-- Memory address of struct
--|------------------------------------------------------------------------
struct_size: INTEGER
do
Result := c_struct_size
end
--|========================================================================
feature -- Status setting
--|========================================================================
dispose
do
if ok_to_free_address and then is_valid_address (address) then
c_free_memory (address)
end
end
--|========================================================================
feature -- Access
--|========================================================================
--|========================================================================
feature -- Comparison
--|========================================================================
--|========================================================================
feature -- Element change
--|========================================================================
--|========================================================================
feature -- Element removal
--|========================================================================
--|========================================================================
feature -- Persistence support
--|========================================================================
--|========================================================================
feature -- Serialization support
--|========================================================================
--|========================================================================
feature -- Conversion
--|========================================================================
--|========================================================================
feature -- Validation
--|========================================================================
is_valid_address (v: POINTER): BOOLEAN
-- Is 'v' a valid address? (i.e. not null)
do
Result := v /= Default_pointer
end
is_valid_size (v: INTEGER): BOOLEAN
-- Is 'v' a valid size for Current?
do
Result := v >= 4
end
--|========================================================================
feature {NONE} -- Implementation
--|========================================================================
allocate_structure_memory
-- Allocate new memory for Current
require
not_allocated: address = Default_pointer
do
address := c_allocate_memory (1, struct_size)
end
--|------------------------------------------------------------------------
copy_struct (other_struct: POINTER)
-- Copy the contents of the other structure into our allocated memory
require
valid_source: other_struct /= Default_pointer
local
pr: POINTER_REF
do
create pr
pr.set_item (address)
pr.memory_copy (other_struct, struct_size)
end
--|------------------------------------------------------------------------
deref_p (p: POINTER): POINTER
-- The value of the pointer to which point 'p' points
-- (*p)
do
Result := deref (p)
end
ok_to_free_address: BOOLEAN
-- Is it OK to free the struct pointer?
dollar_to_addr (v: POINTER): POINTER
-- Return 'v' unchanged
-- Convenience function when address expressions are not enabled
require
pointer_is_valid: v /= Default_pointer
do
Result := v
end
--|========================================================================
feature {NONE} -- Externals
--|========================================================================
deref (p: POINTER): POINTER
-- Quite literally *p
external
"C [macro <stdio.h>] (char**): EIF_POINTER"
alias
"*"
end
--|------------------------------------------------------------------------
c_allocate_memory (num, sz: INTEGER): POINTER
-- Allocate num*sz bytes of zeroed memory
external
"C [ macro <stdio.h> ]"
alias
"calloc"
end
--|------------------------------------------------------------------------
c_free_memory (v: POINTER)
-- Free the memory bound to the already allocated pointer 'v'
require
pointer_is_valid : v /= Default_pointer
external
"C [ macro <stdio.h> ]"
alias
"free"
end
--|========================================================================
feature {NONE} -- Constants
--|========================================================================
c_struct_size: INTEGER
-- REDEFINE IN CHILD
-- The size of the structure in memory, according to the C
-- compiler
-- Change stdio.h to the name of the file containing the struct
-- definition, and change the arg to sizeof() to be the struct
-- type name.
external
"C [ macro <stdio.h> ] : EIF_POINTER"
alias
"sizeof(char)"
ensure
valid_size: is_valid_size (Result)
end
--|--------------------------------------------------------------
invariant
address_exists: is_valid_address (address)
has_valid_size: is_valid_size (struct_size)
--|----------------------------------------------------------------------
--| History
--|
--| 001 26-Oct-2013
--| Created original module from ancient older version (Eiffel 7.2)
--|----------------------------------------------------------------------
--| How-to
--|
--| This class should be inherited, with its c_struct_size feature
--| redefined to represent accurately the size of the structure in
--| bytes. This is done by replacing "char" in the sizeof call with
--| the "struct x" for that particular struct. (use the typedefed
--| name if it has been typedefed).
--|
--| If you fail to so, you will allocate only one byte and you
--| will quickly blow up!
--|
--| To gain access to the fields of the struct, you must implement
--| separate get/set features for each field. The first argument to
--| the feature must be the address.
--| Here are some examples from struct tm.
--|
--| c_tm_sec (p: POINTER): INTEGER
--| external
--| "C [struct <time.h>] (struct tm): EIF_INTEGER"
--| alias
--| "tm_sec"
--| end
--|
--| c_set_tm_sec (p: POINTER; v: INTEGER)
--| external
--| "C [struct <time.h>] (struct tm, int)"
--| alias
--| "tm_sec"
--| end
--|
--|----------------------------------------------------------------------
end -- class AEL_STRUCT
<<<<<