none
Importar dll con dato LPSTR RRS feed

  • Pregunta

  • Hola,

    Quiero usar una dll para poder leer de una tarjeta. La función que me da problemas es la siguiente:

    short FAR PASCAL ND_ReadChanAI(unsigned short com_port, unsigned short m_id, unsigned short ch_no, LPSTR data);

    Yo la importo de la siguiente manera:

    [DllImport("Dll6.dll")] static short ND_ReadChanAI(unsigned short com_port, unsigned short m_id, unsigned short ch_no, [MarshalAs(UnmanagedType::LPStr)]Int16^ data);

    Y a la hora de usarla:

        Int16^ dat ;
        Result = NSDLL6::ReadAI(3,1,0x20, dat );

    He probado cambiando el tipo de dat a SByte^ y String^, tanto en DllImport como en la llamada, pero nada.

    ¿Cómo se declara esa variable?¿Estoy importando mal la dll?

     

    Gracias y un saludo.


    Liiid
    • Editado Liiid miércoles, 25 de enero de 2012 16:39
    miércoles, 25 de enero de 2012 16:37

Respuestas

  • jeje, cómo me disgusta C++/CLI. :P  Pero bueno, gustos personales aparte, le muestro cómo declararía y usaría esa función en C#:

     

    [DllImport(dll6.dll", CharSet = CharSet.ANSI, CallingConvention = CallingConvention.StdCall]
    public static extern short ND_ReadChanAI(ushort com_port, ushort m_id, ushort ch_no, StringBuilder data);
    
    //Y se usaría así:
    ushort tamBuffer = 100; //El tamaño del buffer para recibir los datos.
    StringBuilder sb = new Stringbuilder(tamBuffer);
    ushort r = ND_ReadChanAI(elPuerto, elID, tamBuffer, sb);
    

     


    Como verá, para recibir texto de una función se utiliza StringBuilder y debe reservarse de antemano la cantidad de bytes requerida para almacenar los datos.

    Asumo que el parámetro llamado ch_no es el número de caracteres disponibles en el buffer de salida del texto y por eso lo utilizo en la creación del objeto StringBuilder.

    En general, funciones que devuelven texto suelen retornar el número de caracteres requerido para almacenar la función en caso de que el buffer provisto no sea suficiente, así que le recomiendo leer cuidadosamente la documentación de esta función para determinar exactamente cómo proceder.

    Y sí, esto lo puede traducir a C++/CLI pues es 100% .net, que es independiente del lenguaje utilizado.

    NOTA:  Como usted está usando C++/CLI, tengo entendido que puede usar esta función directamente sin necesidad de hacer marshaling.  No me pida detalles de cómo porque no sé, pero en teoría puede usarla como si fuera C++ común y corriente:

    unsigned short tamBuffer = 100;
    LPSTR szData = new char[tamBuffer];
    unsigned short r = ND_ReadChanAI(elPuerto, elID, tamBuffer, szData);
    //Si ocupa el dato en .net, haga marshaling de szData a String^, que no sé cómo se hace.



    Jose R. MCP
    • Editado webJoseModerator miércoles, 25 de enero de 2012 16:54
    • Marcado como respuesta Liiid jueves, 26 de enero de 2012 14:15
    miércoles, 25 de enero de 2012 16:50
    Moderador

Todas las respuestas

  • jeje, cómo me disgusta C++/CLI. :P  Pero bueno, gustos personales aparte, le muestro cómo declararía y usaría esa función en C#:

     

    [DllImport(dll6.dll", CharSet = CharSet.ANSI, CallingConvention = CallingConvention.StdCall]
    public static extern short ND_ReadChanAI(ushort com_port, ushort m_id, ushort ch_no, StringBuilder data);
    
    //Y se usaría así:
    ushort tamBuffer = 100; //El tamaño del buffer para recibir los datos.
    StringBuilder sb = new Stringbuilder(tamBuffer);
    ushort r = ND_ReadChanAI(elPuerto, elID, tamBuffer, sb);
    

     


    Como verá, para recibir texto de una función se utiliza StringBuilder y debe reservarse de antemano la cantidad de bytes requerida para almacenar los datos.

    Asumo que el parámetro llamado ch_no es el número de caracteres disponibles en el buffer de salida del texto y por eso lo utilizo en la creación del objeto StringBuilder.

    En general, funciones que devuelven texto suelen retornar el número de caracteres requerido para almacenar la función en caso de que el buffer provisto no sea suficiente, así que le recomiendo leer cuidadosamente la documentación de esta función para determinar exactamente cómo proceder.

    Y sí, esto lo puede traducir a C++/CLI pues es 100% .net, que es independiente del lenguaje utilizado.

    NOTA:  Como usted está usando C++/CLI, tengo entendido que puede usar esta función directamente sin necesidad de hacer marshaling.  No me pida detalles de cómo porque no sé, pero en teoría puede usarla como si fuera C++ común y corriente:

    unsigned short tamBuffer = 100;
    LPSTR szData = new char[tamBuffer];
    unsigned short r = ND_ReadChanAI(elPuerto, elID, tamBuffer, szData);
    //Si ocupa el dato en .net, haga marshaling de szData a String^, que no sé cómo se hace.



    Jose R. MCP
    • Editado webJoseModerator miércoles, 25 de enero de 2012 16:54
    • Marcado como respuesta Liiid jueves, 26 de enero de 2012 14:15
    miércoles, 25 de enero de 2012 16:50
    Moderador
  • He probado las dos opciones:

    1.- [DllImport("Dll6.dll", CharSet = CharSet::Ansi, CallingConvention = CallingConvention::StdCall)] static short ND_ReadChanAI(unsigned short com_port, unsigned short m_id, unsigned short ch_no, StringBuilder^ data);

    StringBuilder^ data = gcnew StringBuilder(100);
    Result = ND_ReadChanAI(comm_port, address1, CHANNEL5, data); //CHANNEL5 no es el num de caracteres es otro parámetro

    2.- [DllImport("Dll6.dll", CharSet = CharSet::Ansi, CallingConvention = CallingConvention::StdCall)] static short ND_ReadChanAI(unsigned short com_port, unsigned short m_id, unsigned short ch_no, LPSTR data);

        LPSTR data = new char[100];
        Result = ReadChanAI(comm_port, address1, CHANNEL5, data);

     

    Pero sigo sin poder leer el dato.

     

    La documentación de la función es la siguiente:

    @ Syntax:
    - Visual C/C++, Borland C++
    I16 ND_ReadChanAI (U16 com_port, U16 m_id, U16 ch_no, DATA data)
    - Visual Basic
    ND_ReadChanAI (ByVal com_port As Integer, ByVal m_id As Integer, ByVal ch_no
    As Integer, ByVal data_str As String) As Integer
    - Delphi
    ND_ReadChanAI (com_port : Word; m_id : Word; ch_no : Word; data : PChar) :
    Smallint
    @ Argument:
     - com_port : The COM port that the module connected. The valid values are within 1
    and 4. 1, 2, 3, and 4 represent COM1, COM2, COM3, and COM4
    respectively.
    - m_id : the module ID, the valid value must be within 0 and 255.
    - ch_no : analog input channel number.
    - data : the string contained the analog input data read. It should contain 7
    characters. It consists an + or - sign followed by five decimal digits and
    a decimal fixed point. The format is engineering


    Liiid
    • Editado Liiid jueves, 26 de enero de 2012 9:46 Añadir información
    jueves, 26 de enero de 2012 9:39
  • Hola de nuevo,

    He probado con otra función usando StringBuilder y recido datos!!

    Así que el error que me da en esa función se debe a otra cosa...

    Gracias!Saludos!


    Liiid
    jueves, 26 de enero de 2012 10:54
  • Pues la documentación dice que el parámetro data es un dato de entrada y no de salida.  Dice que debe ser de 7 caracteres y consiste en un símbolo (+ o -) seguido de cinco dígitos decimales y un punto decimal.  O sea, usted está tratando de sacar texto de una función que no devuelve texto.
    Jose R. MCP
    jueves, 26 de enero de 2012 13:39
    Moderador
  • Data devuelve una cadena de caracteres, eso estaba todo correcto.

    El problema está ya resuelto. El fabricante daba los identidficadores de los canales mal.

    Gracias!


    Liiid
    jueves, 26 de enero de 2012 14:14