Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





problemas uso de librerías

Iniciado por Buffon, 13 de Marzo de 2008, 02:05:21 PM

« anterior - próximo »

Buffon

Tengo el siguiente problema:

Tengo desarrollada una dll en Visual Studio 2005, volver a windows ..., la cuál funciona sin ningún tipo de problemas, pero ahora la empresa que nos compra el producto ha pedido que le enviemos un ocx.

Buscando por internet, Visual Studio 2005 ha dejado de lado la posibilidad de hacer ocx para C, lo cuál me ha hecho realizar un wrapper con Visual Studio C++ 6.0 de la siguiente manera:

* Compilo la dll de modo que se genere como .lib así poder linkarla estáticamente.
* dentro del wrapper ocx creo funciones que simplemente llamen a las de la librería.

y aquí es donde falla, al intentar linkar la librería da el siguiente error:


LINK : fatal error LNK1196: invalid or corrupt import object: unknown version



Según he encontrado por internet, desde visual studio 6.0 no se pueden linkar librerías hechas con una versión superior de Visual Studio, un bug acojonante, pero además las versiones superiores de Visual Studio 6.0 no permiten realizar los ocx que necesito.

Para haceros una idea, la dll pesa 60 Mb, pasar todo ese código de nuevo a Visual Studio 6.0 puede llegar a ser insufrible, hay alguna opción mejor ?

Tei

No tengo ni puta idea.

¿Puedes engañar a Visual Studio 2005 para que utilice el enlazador de Visual Studio 6 a la hora de compilar tu lib desde ese montón de obj? supuestamente obj es un estandar, si Microsoft respeta el estandar obj, deberia ser interoperable.

Zaelsius

Los ficheros objeto son dependientes del compilador, hasta donde yo sé... aunque MS suele manter los .lib compatibles entre algunas versiones de VC, no está obligado por ningún estándar.

Creo que Buffon está bien jodido :lol: . Obviamente pasar todo ese código de VC8 a VC6 no es moco de pavo... y no se me ocurre otra manera. Además, portarlo no solo implica reescribir código. Aparecerán nuevos errores (el VC6 tiene bastantes pecularidades), tendréis que hacer una fase de pruebas de la librería al completo, decidir si se mantiene una rama VC6 y otra VC8 o se unifica... un follón y un esfuerzo bestial para todo el código que me imagino que tenéis.

A estas alturas... lo ideal sería que el cliente se pasase a VB.Net, y si no que asuma el coste ;) aunque tampoco estoy seguro de que os interese meteros en semejante marrón.

Juan Mellado

Erh.. una duda que no puedo resistirme a preguntar: ¿qué quiere decir que "Visual Studio 2005 ha dejado de lado la posibilidad de hacer ocx"? ¿Pero los que OCXs al fin al cabo no eran DLLs con una serie de interfaces y tal? Me estoy perdiendo algo. Perdón si es algo obvio que estoy ignorando.

Respecto a tu problema, "tal y como está planteado", sólo se me ocurre que enlaces dinámicamente la DLL desde el OCX. Entiendo que implica distribuir dos ficheros en vez de sólo con todo encapsulado, pero al fin y al cabo también estarás utilizando seguramente algunas otras  DLLs que das por supuestas que existen, como las del sistema operativo por ejemplo. Siempre queda el remedio de empaquetar la DLL como un recurso del OCX, extraerla en runtime y enlazarla dinámicamente, pero no es precisamente una técnica muy "ortodoxa".

Saludos

[EX3]

A grandes rasgos, un OCX diferia de una DLL comun en dos cosas, la primera que era un compoente ActiveX y la segunda que solia ser uno o varios controles, visuales o no, que se instanciaban automaticamente en formularios u otros objetos de interfaz del entorno de desarrollo, Visual Basic 6.0 por ejemplo (aunque los OCX tambien se pueden instanciar por codigo en muchos de los casos), lo que a diferencia de una DLL comun o una DLL ActiveX es que tienen que tener un componente visual como minimo (visual aunque sea en tiempo de diseño a modo de icono representativo del objeto). Visual Studio 2005 soporta el uso de ActiveX a traves de COM pero no tiene metodos para generar OCX como tal, al menos en .NET ahora trabajan enteramente con "componentes", que seria lo mismo que un ensamblado pero con interfaz grafica e instancia automatica sobre WinForms (un OCX pero sin ActiveX). Lo que si recuerdo es que los ensamblados de .NET se pueden compilar con compatibilidad COM, no se si el VC++ 2005 existe esta posibilidad.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

Buffon

Cita de: "Juan Mellado"Erh.. una duda que no puedo resistirme a preguntar: ¿qué quiere decir que "Visual Studio 2005 ha dejado de lado la posibilidad de hacer ocx"? ¿Pero los que OCXs al fin al cabo no eran DLLs con una serie de interfaces y tal? Me estoy perdiendo algo. Perdón si es algo obvio que estoy ignorando.

Respecto a tu problema, "tal y como está planteado", sólo se me ocurre que enlaces dinámicamente la DLL desde el OCX. Entiendo que implica distribuir dos ficheros en vez de sólo con todo encapsulado, pero al fin y al cabo también estarás utilizando seguramente algunas otras  DLLs que das por supuestas que existen, como las del sistema operativo por ejemplo. Siempre queda el remedio de empaquetar la DLL como un recurso del OCX, extraerla en runtime y enlazarla dinámicamente, pero no es precisamente una técnica muy "ortodoxa".

Saludos

El problema es que la empresa que nos compra el producto quiere sólo componentes únicos.

Nos ha pedido un desarrollo en el cuál se ha de distribuir para poderse usar en varias plataformas/medios.

DLL + OCX + JAR

Ahora seguramente preguntaréis para que quieren un OCX si tienen un JAR. Nosotros también nos lo preguntamos pero como ellos pagan, ellos mandan y al parecer quieren usar con IE el ocx y con Firefox u otro navegador el compilado en java. en sus instalaciones tendrán el OCX corriendo para los clientes, pero si cuento más me cortan los huevos jeje :P

El desarrollo del OCX con Visual Studio 6.0 se basaba en que era un control tal cuál, no requería ser un control gráfico, simplemente era un activex como un control básico y simple, con Visual Studio 2005 la forma más sencilla de hacerlo en C++, era como un control MFC, que es como se ha hecho al final.

Y no, no podemos distribuir el control OCX que cargue dinámicamente la DLL por que ellos no quieren eso, quieren tener componentes individuales y las librerías que dependa sean mínimas y estén siempre en el sistema.

Resuelto el primer punto ahora me surge otra duda:

El wrapper ocx ya está hecho y "exporto" todas las funcionalidades de la librería para poderse usar en un navegador, pero ahora hay un pequeño problema.

Las dos siguientes funciones:

componente OCX
void ax_funcion1(BSTR data, LONG length);
void ax_funcion2(BSTR* data, LONG length);


JAVASCRIPT
Hay un gran problema, por que no puedo llamar a las funciones con puntero, ni puedo hacer reinterpret_cast de un VARIANT a un puntero así. En cambio si puedo llamar a la funcion que no usa punteros y se ejecuta correctamente.

Quizá no veis problema por que sólo hay un elemento con puntero y se podría "recoger" como un [out,returnvalue] pero en el proyecto hay llamadas que devuelven hasta 6 valores.

En el siguiente código, la llamada a funcion1 se ejecuta correctamente, y muestra el resultado esperado, pero la llamada a funcion2 no llega siquiera a ejecutarse.


<html>
<head>

<SCRIPT LANGUAGE=javascript>
function funcion1()
{
mydata = "Datos a enseñar";
mylength = 0;
OCXId.ax_funcion1(mydata,mylength);
}

funcion funcion2()
{
mydata = "Datos a enseñar";
mylength = 0;
OCXId.ax_funcion2(mydata,mylength);
}

function window_onload()
{
funcion1();
funcion2();
}
</SCRIPT>

</head>
<body LANGUAGE=javascript onload="return window_onload()" >

<OBJECT CLASSID="clsid:{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
id=OCXId />

</body>
</html>


Para corregir este problema habia pensado en utilizar Propiedades dentro del ocx, y en la cabecera de cada llamada indicar cuales modifican su valor en caso que la ejecución sea correcta, cambiaria la función para que devolviera LONG con el resultado de la ejecución.

El único problema es que no sigue el comportamiento que tiene la librería en si, y que además tener todas las propiedades públicas es un fallo de programación desde mi punto de vista.


VISUALBASIC SCRIPT
Ocurre exactamente lo mismo que con JAVASCRIPT, no puedo llamar a las funcionalidades que utilizan punteros y me vería obligado a utilizar propiedades de nuevo.

PD: no pongo el código por que es muy similar al de javascript, pero si alguien le hace ilusión que me mande un privado.


ASP.NET Web Service Application
Estoy en proceso de investigación ahora, nunca he trabajado desarrollando webs y mucho menos servicios para ellas, pero la empresa que nos compra la librería tienen "expertos" en C# y es siempre un golpe a favor enviar un ejemplo que ellos entiendan rápido, pero primero tendría que entenderlo yo !!! jeje

Alguien sabe como hacer una pequeña página web con C# que no salga el feo botón INVOKE ? cómo importar un OCX supongo que lo encontraré rápido.

Alguien sabe si se podrán realizar llamadas utilizando punteros ? da igual si tengo que usar la directiva o macro unsafe {}


Lo siento por el rollazo !!!!

Prompt

Joer aqui hay muchas cosas juntas...

Usar BSTR* requiere el puntero al primer elemento de un array de char (autoctono de ATL) pero no puedes hacer que sea una reserva de memoria dinamica. No se si me he explicado bien. Y no se si estás teniendo ese problema derivado de lo que te digo.

Buffon

Cita de: "Prompt"Joer aqui hay muchas cosas juntas...

Usar BSTR* requiere el puntero al primer elemento de un array de char (autoctono de ATL) pero no puedes hacer que sea una reserva de memoria dinamica. No se si me he explicado bien. Y no se si estás teniendo ese problema derivado de lo que te digo.

nope,

el problema es que no consigo realizar una llamada si la declaración contiene un puntero, fuera que yo modifique la información o no en el activex.

En cambio si llamo directamente usando BSTR sin puntero, dentro leo el contenido, lo modifico internamente pero como no es puntero lógicamente no puedo devolverlo, en cambio si pudiera realizar esta llamada utilizando punteros, el javascript podría realizar la llamada y recuperar esa información.

Prompt

No se puede usar en ATL BSTR*. No se permiten cadenas de tamaño no definido o dinámico. Ni te imaginas la de problemas que me dió eso al hacer el Web Service en C++. Devuelve el parametro con los datos.

No obstante si que tengo:

[id(1), helpstring( "Descripcion." )]
HRESULT funcionAbsurda( [in] BSTR _message, [in] int  _nVeces );

[id(2), helpstring( "Descripcion." )]
HRESULT funcionAbsurda( [in] BSTR _message,  [out, retval] miStruct* _pStruct );


De todas formas, es que tu problema es que java script manda un puntero mmmm, puedes hacer muchos fakes metiendo poco a poco el string o alguna warrada así.

No puedes pasarle el contenido y no el puntero con java script? o pasandole un "const char" ?

Buffon

El problema es que ya estamos tratando con la filosofía Microsoft.

según microsoft, cuando una librería devuelve datos se ha de enviar un puntero al buffer de memoria que se ha de rellenar, en el caso de no saber cuanto buffer necesitas le has de pasar NULL y el te devolverá el espacio que necesita.

Lo que implica el siguiente comportamiento.


{

unsigned char * datos = NULL;
int length = 0,ret = -1;


if( llamadaMicrosoft(datos,&length) != SUCCESS)
return ERROR;

datos = (unsigned char *)calloc(length,sizeof(unsigned char));
if( llamadaMicrosoft(datos,&length) != SUCCESS)
return ERROR;

return SUCCESS;

}


desde nuestro desarrollo se ha seguido la misma casuistica por que no podemos inferir en asignar memoria desde la librería al buffer que nos pasan, esto sería totalmente incorrecto por varios motivos:

1. La asignación de memoria siempre ha de residir en el programador por que podría preferir otro tipo de inicialización fuera del new.
2. Si una librería reserva memoria para un buffer luego ha de liberarla, sino se ha de poner en la cabecera que el programador lo haga y estos no suelen complicarse siquiera en liberar la que ellos reservan.

Desde el wrapper OCX se sigue esa casuística, se llama a una función que devolverá la información y esta internamente hace la llamada a nuestra librería pasando NULL, mirando si ha ido bien la secuencia, volviendo a llamar para rellenar los datos en el buffer y devolviendolo de nuevo al lenguaje que se esté utilizando, ya sea javascript, vbscript o asp.net.

Sobre tu código prompt

HRESULT funcionAbsurda( [in] BSTR _message,  [out, retval] miStruct* _pStruct );


esta función tenia pensada pero tiene un problema o quizá no.

como utilizas desde javascript miStruct?

los datos que devuelvo son unsigned char * y la longitud del buffer, y no, no puedo devolver sólo el unsigned char * por que si o si contendrá varios '\0' en su interior y estos se malinterpretarían.

['C' 'A' 'S' 'A' '\0' 'S' 'A' 'N' 'C' 'H' 'O' '\0' '\0']

que es la putada de utilizar multistrings de Microsoft.

pero también devuelvo datos que pueden llegar a contener varios '\0' seguidos y no sería correcto hacer una búsqueda, sino que debería tener la longitud preestablecida.

PD: Muchas gracias por el tiempo que estás dedicando prompt, después de leer todo este parrafote creo que tengo la solución delante mia jeje. Si funciona la pondré.

Prompt

Veamos, como comentamos el problema es la reserva de memoria dinamica con ATL.

Como tu bien dices, para solucionar esto, "desde fuera" de esa DLL o OCX, es pasarle NULL a la función y esta devolverá el tamaño para que tu reserves memoria y no pase nada.

Esto lo tienes ya solucionado. Yo tuve que hacer la solución desde dentro y tuve este mismo problema para la gestion interna, entre el WebService con ATL y C / C++ y el un servidor.

Tenemos solucionado el recivir un string, cadena de chars, desde fuera utilizando las funciones con ATL y estos malditos ATL-BSTR*.

En tu caso, cuando dices:
Cita de: "Buffon"como utilizas desde javascript miStruct?

Y tu problema de cadena con los \0 ( que no se porqué tendría que haber \0 debería haber ESPACIOs ).

Puedes utilizar miStruct* como miString*. El cual definas alineado en memoria ( mirate pragma pak ):

#pragma pack (push, 1)
struct sMiStringParaJavaScript
{
   unsigned int size;
   BSTR*         stringFeote;    // o lo que se te ocurra :P
};
#pragma pack (pop)


Con pragma pack te aseguras de que los primeros bytes que te encuentres en la estructura sean los de size.

Y así solucionas el problema de los \0. Aunque... no se porque diantres tienes \0... y no espacios. Estas formateando la cadena de alguna forma en especial?

Buffon

Cita de: "Prompt"
Y así solucionas el problema de los \0. Aunque... no se porque diantres tienes \0... y no espacios. Estas formateando la cadena de alguna forma en especial?

son los multistrings de windows aunque te voy a poner un ejemplo.

Pongamos que tienes que devolver la siguiente información.

EQUIPO1+EQUIPO2+NOMBREESTADIO

EQUIPO1 = "Las ratas"
EQUIPO2 = "pelaos"
NOMBREESTADIO = "Manchegos S.A."

Si lo devuelves con espacios, no puedes distinguir desde fuera cuál es el equipo 1 del equipo2.

Tal como trata microsoft los multistrings es de la siguiente manera:

lo pongo en lógica:

#token CHAR        "[a-zA-Z][a-zA-Z0-9]*"
#token END          "\0"

multistring = string+ END;
string = CHAR+ END;

con lo cual si representamos

EQUIPO1+EQUIPO2+NOMBREESTADIO

Las ratas\0pelaos\0Manchegos S.A.\0\0

y una vez tengamos el resultado podremos tratarlo.

PD: El problema no es la funcionalidad que devuelve multistrings, sino otra que devuelve un cierto tipo de datos que puede contener cualquier valor de 0x00 a 0xFF.

Aunque ya la tengo organizada para que devuelva una estructura como tu dices.

struct {
length
datos*
}

y datos internamente será:

[length1][info1][length2][info2]...[lengthn][infon]

---

A ver si acabo de una puñetera vez el ocx, se entrega, y puedo contar un poco más de que va el tema jeje

Prompt

Pues pon!

#token END '\1'
Las ratas\1pelaos\1Manchegos S.A.\1\0

Así java script no se cree que ha acabado la cadena :P

Ya nos contarás a ver como te ha ido. Saludos!

Buffon

Cita de: "Prompt"Pues pon!

#token END '\1'
Las ratas\1pelaos\1Manchegos S.A.\1\0

Así java script no se cree que ha acabado la cadena :P

Ya nos contarás a ver como te ha ido. Saludos!

en ese caso debería hacer ruiditos cuando imprima los carácteres por pantalla! :)

Prompt

hahahaha! :D en modo consola xD hahahaha si :D

Bueno algún otro caracter... # o @ o alguno así típico que no se use y en el que por seguridad puedas eliminarlo cuando el usuario lo inserte, o en el textbox que lo rellena no le dejas poner simbolos tipo / ; # @ no se! se pueden buscar alternativas si te molesta solo eso :)






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.