Crear una DLL y llamarla en otro lenguaje

Iniciado por Meta, 27 Julio 2018, 09:58 AM

0 Miembros y 1 Visitante están viendo este tema.

Meta

Hola:

Quiero hacer esto desce cero con Visual studio Community 2017. Creo una dll en Win32 C++. En él solo hay dos cosas, una fórmula matemática y un mensaje. Por ejemplo.

Fórmula matemática:

2 + 3

Mensaje:

Hola. Soy una DLL Win32.

Una vez creada una dll en C++ Win32 con lo indicado arriba, quiero ahora crear otro proyecto con Windows Form hecho bajo el lenguaje C#. En el formulario tiene incluido un label1 para mostrar el mensaje y otro label2 para mostrar el resultado de la suma.

Cualquier cosa que se entienda, lo repito de otra manera. Lo hice así tan sencillo para aprender de una vez y rápido como hacerlo.


Código C++
:
Código (cpp) [Seleccionar]
// $nombredeproyecto$.cpp: define las funciones exportadas de la aplicación DLL.
//

#include "stdafx.h"

extern "C" {
__declspec(dllexport)  int WINAPI Suma(int, int);
__declspec(dllexport) LPTSTR WINAPI Mensaje();
}

BOOL APIENTRY DllMain(HMODULE hModule,
DWORD  ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

int WINAPI Suma(int a, int b) { return a + b; }
LPTSTR WINAPI Mensaje() { return TEXT("Hola. Soy una DLL Win32."); }


En la última línea donde pone TEXT pone error indicado abajo.

Código (cpp,1) [Seleccionar]
LPTSTR WINAPI Mensaje() { return TEXT("Hola. Soy una DLL Win32."); }

Gravedad    Código    Descripción    Proyecto    Archivo    Línea    Estado suprimido
Error (activo)    E0120    el tipo de valor devuelto no coincide con el tipo de función    pepe    c:\Users\Usuario\Documents\Visual Studio 2017\Projects\pepe\pepe\pepe.cpp    28   

En el mismo proyecto de la dll creo la interfaz C#:

Código C#:
Código (csharp) [Seleccionar]
using System;
using System.Runtime.InteropServices; // No olvidar.
using System.Windows.Forms;

namespace Prueba_dll_cs_01
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            label1.Text = Marshal.PtrToStringAuto(PEPE.Mensaje());
            label2.Text = PEPE.Suma(1764, -764).ToString();
        }
    }

    internal class PEPE
    {
        [DllImport("pepe.dll", EntryPoint = "_Suma@8")]
        extern static public int Suma(int a, int b);
        [DllImport("pepe.dll", EntryPoint = "_Mensaje@0")]
        extern static public IntPtr Mensaje();
    }
}


Como dije antes, el problema está en el TEXT que dice el error:  el tipo de valor devuelto no coincide con el tipo de función.

¿Alguna idea?

Saludos.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Eleкtro

#1
¿puedes subir/compartir la dll para tratar de ayudarte con el P/invoking?.

Acabo de leer la documentación de la macro TEXT (https://docs.microsoft.com/en-us/windows/desktop/api/winnt/nf-winnt-text) y quizás esta pudiera ser la definición adecuada:

Código (csharp) [Seleccionar]
[return: MarshalAs(UnmanagedType.LPTStr)]
[DllImport("pepe.dll", CharSet=CharSet.Auto, EntryPoint="_Mensaje@0")]
public extern static string Mensaje();


De todas formas, y sin experiencia por mi parte en C++, me atrevería a decir que me da la sensación de que el tipo de valor de retorno de tu función y el diseño (la firma de la función) es de alguna forma anómalo, tomo como referencia la API de Windows, que yo sepa no hay ninguna función que devuelve un valor LPTSTR ni de ninguna otra clase de texto, sino que por lo general las funciones que manipulan y devuelven cadenas de texto veo que en su lugar devuelven un valor de evaluación de la misma (me refiero, un BOOL, HRESULT o equivalente para determinar si la llamada a la función fue satisfactoriamente) y para devolver una cadena de texto lo que se hace es definir en la firma de la función un parámetro para pasarle un valor por referencia que, cuando la función retorna, dicho valor contiene el string resultante.

Por ende, mi sugerencia, aunque como ya digo sin tener experiencia en C++ (así que no si estaré muy en lo correcto), es que trates de seguir las reglas de diseño de los maestros (Microsoft), para empezar yo diría que deberías cambiar el valor de retorno de tu export a un simple BOOL y devolver true o false según si todo sale bien, y para que tu función "devuelva" un string pues simplemente añade un parámetro a la función que tome un valor LPTSTR por referencia y a esa variable le estableces el string antes de retornar. A esta hipótesis le añado que también he leido por la documentación de MSDN que crear un export con un tipo de valor de retorno LPTSTR es ilegal, no soportado o algo parecido... vamos, que según parece eso debe dar más problemas que otra cosa en este tipo de escenarios, aunque en realidad no lo se por que no manejo C++, solo digo lo que me parece, desde mi ignorancia, pero según lo que leí y creí entender...

Saludos.








Meta

Hola:



Les dejo un mini tutorial rápido en PDF por si alguien lo necesita.

Ver tutorial.

Saludos.

PD: Gracias a los compañeros del foro.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/