BUG: El bug del bool en interop desde C++ nativo

Basta que uno plante un circo para que le crezcan los enanos, y como se puede comprobar si uno mira al jardín de la vecina esa que está tan buena, a veces a uno le crecen sin estar bueno ni haber montado la carpa.


No sé en qué pensarán estos señores de Microsoft, pero que el bug venga arrastrado desde por lo menos 2002 y no esté solucionado clama al cielo. Pero antes de despotricar –que lo haré-, vamos a ver en qué consiste.


Uno tiene una inocente DLL que posee una función que devuelve un valor de tipo bool de C++. Algo así:

extern «C» MIDLL_API bool dllFncDevuelveBool(unsigned char id);

Ahora hace el envoltorio manejado para ser usado en otro lenguaje .NET:

[DllImport(«dllNativa.dll»)]
extern public static bool dllFncDevuelveBool(byte id);

Y a partir de ese momento comienza a utilizarla en su programa, digamos, escrito en C#. Pero pronto uno descubre que… bueno… la función


¡¡siempre retorna cierto!!


Uno empieza a meterse con el depurador y escribe código como este:

bool resp=DLLAdaptor.dllFncDevuelveBool(m_device.ID);
if (resp == false)
MessageBox.Show(«No puedo en este momento.”);»

Pone un punto de interrupción en el comparador y ve que, mientras que la ventana de variables automáticas le dice que la llamada a dllFncDevuelveBool devuelve falso, resp vale cierto. Y para más inri, si entra en la función nativa, en todos lados ve que se está devolviendo falso.


Como el autor tuvo hace unos días un embrollo de narices con algo muy parecido, se pone a buscar la misma solución que encontró con anterioridad. La cosa tuvo su miga, ya que había una función que debía hacer un salto a otra parte del código cuando varias condiciones fueran ciertas, pero el salto se producía siempre o casi siempre, no importaba si se cumplía el comparador o no… Tras varios días de buceo descubrió que se estaba pisando variables, entre ellas las que estaba comparando. El tema era bastante complejo, porque quien pisaba era un hilo y cuando se realizaba la inspección de la variable tenía su valor correcto, pero cuando el código se ejecutaba (dos o tres instrucciones ensamblador después), ya se había pisado y despisado… Vamos un tema de “puntero loco sincronizado”.


Bueno, como la situación era similar, aunque no igual (lo anterior era en C++ puro, en este caso había interop de por medio), el autor se puso a buscar su “memoria pisada” sin encontrar nada de nada.


Al final, cuando estaba hasta las mismísimas narices del tema, se le ocurrió googlear y cuál no fue su sorpresa cuando se encontró entradas, del 2002, como ésta: http://groups.google.com/group/microsoft.public.dotnet.languages.vc/msg/a6d9c1e3015207f0?hl=en&lr=&ie=UTF-8&oe=UTF-8 y esta otra del 2005: http://bytes.com/forum/thread267443.html.


Finalmente, era un bug del Interop de .NET ¡¡que lleva por lo menos 6 años sin ser resuelto!!, y encima es un bug estúpido cuya corrección seguro que apenas requiere una línea de código fuente…


Es decir, cuando una función nativa devuelve un valor booleano nativo de C++, el Interop se equivoca y retorna siempre cierto.


La corrección pasa por colocar algo así en la firma manejada:


[DllImport(«dllNativa.dll»)]
[return: MarshalAs(UnmanagedType.I1)]
extern public static bool dllFncDevuelveBool(byte id);


Vaya usted a saber qué significa I1.


Lo que más me toca las narices del tema es que lleve por lo menos 6 años sin resolver, o si fue resuelto ha vuelto a aparecer. ¿Tan difícil es comprobar algo como esto? Ciertamente siento vergüenza ajena del tema, que algo tan sencillo y tan evidente se conozca desde hace tanto tiempo, sea tan fácil de solucionar, y que nadie le haya hecho ni p*to caso.


En fin, que uno más para la colección: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=355665

4 comentarios sobre “BUG: El bug del bool en interop desde C++ nativo”

  1. Rodri, ya me he dado cuenta del tema. Ramon Sola y Tella han estado hurgando en la llaga en los grupos de Tella, mañana pondré un nuevo post explicando el tema.

    Eso me pasa por no leerme la MSDN antes.

    Aisssssss….

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *