2010-06-29 30 views
5

En un proyecto de C#, necesito pasar los parámetros de objeto poniendo referencias en una estructura. es decir, tengo una estructura pasada a un despachadorConversión de void * a objeto en C#

struct SOMESTRUCT 
{ 
    public int lpObject; 
} 

Dónde lpObject mantiene un puntero a un objeto personalizado como

class SomeClass 
{ 
    private string foo; 
} 

Y la estructura SOMESTRUCT se pasa de un método a otro para finalmente llegar a mi código. No puedo modificar el flujo de ejecución ni el sistema SOMSTRUCT extraño, por lo que supuso que la única solución era emitir mi objeto a un puntero de la siguiente manera:

var myObject = new SomeClass(); 
GCHandle GC = GCHandle.Alloc(myObject, GCHandleType.Pinned); 
int myRef = GC.AddrOfPinnedObject().ToInt32(); 
GC.Free(); 

SOMESTRUCT struct; 
struct.lpObject = myRef; 
someMethod(struct); 

Sin embargo, no puedo encontrar la manera de recuperar los miembros MyObject de los campos de lpObject. Algo como esto:

SomeClass myObject = CastPointerToObject(struct.myRef) as SomeClass; 

¿Hay alguna manera de hacerlo, o es imposible? ¿Cómo puedo decirle al recolector de basura que maneje el objeto? ¿Debo crear un nuevo objeto recogido de basura y copiar el campo de datos por campo?

TYIA,

+0

use IntPtr en lugar de int ....por lo tanto, funcionará también en 64 bits –

Respuesta

4

no No NO NONO !!!

Este

struct SOMESTRUCT 
{ 
    public SomeClass object_ref; 
} 

es la forma correcta de almacenar una referencia en una estructura.

El código que ha escrito y la respuesta aceptada están 100% rotos.

La dirección devuelta por GC.AddrOfPinnedObject(GCHandle) solo es válida mientras el GCHandle está intacto. No debe llamar al GCHandle.Free, y no debe dejar que el GCHandle se recopile. En su código, la dirección ya no tiene sentido cuando la almacena.

Pero debe dejar que .NET se encargue de administrar el puntero durante la recolección de basura, mediante el uso de una variable de tipo de referencia. Entonces no necesitas saltar a través de los aros. La única razón para tomar la dirección de un objeto administrado es cuando se pasa a una función DLL nativa existente que guardará el puntero después de que regrese. Por ejemplo, es necesario con matrices de buffer OpenGL. NO es necesario, nunca, al llamar a otros métodos de C#.

Si SOMESTRUCT es en realidad un tipo de datos nativo utilizado por alguna función de DLL que no ha mencionado, entonces deberá asegurarse de mantener el GCHandle activo. Solo mientras exista el GCHandle, el puntero que tenga seguirá siendo válido.

+0

De acuerdo. La respuesta aceptada no es correcta; sin embargo, creo que hay más en la historia que no conocemos, de lo contrario, ¿por qué todo el trabajo extra cuando el tiempo de ejecución se las arreglaría correctamente? – codekaizen

+0

@codekaizen: Sí, el requisito de que "el tipo SOMESTRUCT no se puede cambiar" debe tener algún fundamento que necesitamos saber para resolver el programa correctamente. –

+0

El tipo SOMESTRUCT es una estructura de mensaje de ventana con un "puntero personalizado". Este puntero se usó originalmente (en el programa) para hacer referencia a cadenas que contenían objetos serializados, que funcionaban (tipo de) fino. En mi código, algunas clases no eran serializables, así que tuve que buscar otra solución. De hecho, la solución aceptada parecía correcta pero nunca fue probada, ya que planteó más problemas que resolvió; así que dejé la cosa de "puntero/serialización" y usé una forma más C de C -ish de hacer las cosas. – slaphappy

2

¿Quiere decir que desea emitir el puntero devuelto de nuevo a una estructura?

similares a:

lvHitTestInfo = (LVHITTESTINFO)Marshal.PtrToStructure(lP, typeof(LVHITTESTINFO)); 

Dónde lvHitTestInfo es una estructura y un puntero lp.

O no entendí su pregunta correctamente. Tal vez puedas explicar más (muestra de código más completa).

+0

Sí y no. Quiero lanzar el puntero devuelto a un objeto. Añadiré más detalles a mi pregunta. – slaphappy

+0

No me di cuenta de que este método funciona también con objetos. Esto es lo que estaba buscando. Gracias por tu ayuda ! – slaphappy

+0

Nunca he ido allí, pero para saber si es posible, debe dar una descripción exacta de lo que realmente se devuelve. ¿A qué apunta exactamente el puntero? Mira, si estás interactuando con código no administrado, es muy poco probable que puedas enviar contenido a un objeto administrado. No hay forma de saber qué va a dónde. – Jeroen