2010-02-03 16 views
8

Necesito leer un campo blob de una base de datos en una aplicación C#.Cómo leer una matriz Delphi de cadenas de tamaño fijo dentro de un registro empaquetado en C#

Sin embargo el campo blob se escriben en la base de datos por una aplicación Delphi usando el siguiente método:

procedure WriteABlob(Blob : TBlobField; var Buffer; size : integer); 
var 
    s : String; 
begin 
    setlength(s,size); 
    move(buffer,s[1],Size); 
    Blob.Value := S; 
end; 

La Estructura escrito a la base de datos no es una estructura simple y contiene cosas como

MyVariable : Array[0..3] of String[80]; 

o peor algunos de ellos contienen

MyRecord = Packed Record 
case byte of 
    1: (
     iValue:Integer; 
     ) 
    2: (
     cValue:Char; 
     ) 
end; 

He estado intentando r eading en los bytes de la base de datos y luego usando

Marshal.PtrToStructure() 

a fin de avanzar en la estructura

Mi Struct se define de la siguiente manera:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1, Size = 10710)] 
    public struct MyBlobField 
    { 
     ... 
     [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.AnsiBStr,SizeConst = SpecificArraySize)] 
     public String[] ArrayofFixedLengthStrings; 
     ... 
    } 

pero me da un error al llamar Marshal.PtrToStructure():

no se puede Mariscal de campo '' ArrayofFixedLengthStrings de tipo 'MyBlobField': no ​​válido combinación de tipo administrado/no administrado (String [] debe estar emparejado con un ArraySubType de LPStr, LPWStr, BStr o LPTStr).

Me preguntaba si había un atributo que pudiera definir en un CustomMarshaler que aceptar un emparejamiento con un String []

¿Alguna idea de cómo podría leer el contenido de la burbuja en C#?

+0

¿Es realmente un AnsiBstr y no un Bstr (es decir Unicode) regular. Eso es bastante no estándar. –

+1

Versiones anteriores de Delphi (incluido D2007) estandarizadas en Ansi en lugar de Unicode. –

Respuesta

2

lo descubrió ...

Declarado String20 estructura como

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] 
    public struct String20 
    { 
     [MarshalAs(UnmanagedType.U1)] 
     public byte StringSize; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] 
     public String Value; 
    } 

Al parecer, el identificador de tamaño de la cadena en el comienzo de una cadena de longitud fija (es decir, un delphi ShortString) es de sólo 1 byte. luego cambió la definición de header_identifiers a:

 [MarshalAs(UnmanagedType.ByValArray, SizeConst = max_header_identifiers)] 
     public String20[] header_identifiers; 

también encontraron que Delphi para llevar booleana necesita ser elegida como

[MarshalAs(UnmanagedType.I1)] 
public bool BooleanVar; 
0

Mi primer comentario es que la "Cadena [80]" es una cadena de longitud fija (que debería ser más fácil de manejar en una estructura), y en C# intentas ponerla en "Cadena []" - que en realidad es una referencia (puntero) a una cadena.

Mi siguiente comentario es que, en el peor de los casos, podría intentar leerlo en una matriz de bytes, extraer los bytes que necesita y manipularlos en la estructura de destino.

+0

¡Estaba intentando ponerlo en una serie de cuerdas! Mis otros pensamientos estaban en la línea de lectura en un entero seguido por 3 AnsiBStr en cadenas normales (es decir, aplanar la matriz e ignorar su parámetro de tamaño). ¿Eso significa que si uso una interfaz ICustomMarshal y devuelvo un puntero en lugar de un objeto, puedo usar un CustomMarshaler para una matriz? Supuse que era un atributo. Este no es el único blob que tenemos así y este solo es 10k. Preferiría no seguir la ruta de las matrices de bytes por el momento. –

Cuestiones relacionadas