Al di là del titolo stupido, i problemi di "convivenza" tra PocketPC e codice
nativo C++ che citavo in precedenza sono stati risolti grazie
alla segnalazione di : su MSDN ci sono una serie di articoli che spiegano + o -
tutto quello che c'è da sapere... compreso il problema della ridenominazione dei
metodi, che in realtà si chiama Name Mangling:
basta aggiungere alla firma dei metodi extern "C"
per evitare la modifica del nome dei
metodi!
Per quanto riguarda il problema dell'eccezione
NotSupportedException
generata se
si usano come tipo di ritorno double o string (vedete il post precedente per chiarire il tipo di problema a cui mi
riferisco), l'eccezione viene ovviamente generata dal codice .NET, come
riportato qui:
" This occurs if the arguments passed to the method
contain invalid data, or if the function itself is declared with improper
arguments. In this case, a NotSupportedException
will be
thrown. If this occurs, you should re-examine your declaration to determine if
it matches the actual DLL definition. "
Quindi, semplicemente, una firma come questa
__declspec(dllexport) double __stdcall DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField,);
nel Framework 1.1 richiede questa
dichirarazione DllImport,
[DllImport("shapelib.dll", CharSet=CharSet.Unicode)]
public static extern double DBFReadDoubleAttribute (IntPtr hDBF, int iShape, int iField);
dichiarazione che però non è valida per il Compact
Framework! Per capirne il motivo basta continuare nell'articolo indicato in precedenza, e controllare la
lista dei Blittable Types, ovvero:
" ... types will have a common representation in both the .NET Compact
Framework and unmanaged code.
CF type |
VB
keyword |
C#
keyword |
System.Byte |
Byte
|
byte |
System.SByte |
n/a |
sbyte |
System.Int16 |
Short |
short |
System.UInt16 |
n/a |
ushort |
System.Int32 |
Integer |
int |
System.Int64 |
Long (only
ByRef) |
long (only
ref) |
System.UInt64 |
n/a |
ulong |
System.IntPtr
System.Char
System.String
System.Boolean |
n/a>
Char
String
Boolean |
* using unsafe char
string
bool
| < P>
In other words, the marshaler doesn't need to perform any special
handling of parameters defined with these types in order to convert them between
managed and unmanaged code. In fact, by extension, the marshaler
needn't convert one-dimensional arrays of these types, or even structures and
classes that contain only these types. "
Come si vede non ci sono i tipi
double, e + in generale non
interi; infatti...
"
These types cannot be marshaled by value by the
.NET Compact Framework. However, they can be marshaled by
reference, and passed as pointers to an unmanaged function that acts as
a wrapper or shim. "
Per quanto riguarda le stringhe invece...
" As just mentioned,
strings in the .NET Compact Framework are blittable types, and are represented
to unmanaged functions as null-terminated arrays of Unicode characters. At
invocation time, since System.String
is a reference type (it is allocated on the
managed heap, and its address is stored in the reference variable), and
even though it is being passed by value, the marshaler passes a pointer to the
string to the unmanaged function... ".
Presumo quindi che sia per questo motivo che nei
fatti una funzione C++ di questo tipo:
__declspec(dllexport) const wchar_t* __stdcall DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField,);
non funzioni con questa DllImport
[DllImport("shapelib.dll", CharSet=CharSet.Unicode)]
public static extern string DBFReadStringAttribute (IntPtr hDBF, int iShape, int iField);
comportandosi esattamente come la precedente
funzione che ritorna un double.
In conclusione, perchè il titolo "la rivincita di
.NET" ?
Semplice, xchè, seguendo il suggerimenti di Roberto
Messora, alla fine ho optato per gestire in .NET la lettura/scrittura dei
DBF, a partire dalle funzioni IO presenti in GeoTools.NET!
powered by IMHO 1.3