PDA

View Full Version : [C++] Come creare una DLL


Tubo Catodico
29-01-2014, 14:34
Di nuovo ciao, ho un'altro problema. Ho necessità di capire come posso creare e compilare una DLL con il C++ e Visual Studio. Stavo pensando ad una DLL caricata a Load Time, anche perchè dovrebbe essere più semplice. Apprezzo qualsiasi consiglio e, meglio ancora, link a tutorial e guide sia in italiano che in inglese.

Di nuovo grazie. ;)

sottovento
30-01-2014, 04:56
Di nuovo ciao, ho un'altro problema. Ho necessità di capire come posso creare e compilare una DLL con il C++ e Visual Studio. Stavo pensando ad una DLL caricata a Load Time, anche perchè dovrebbe essere più semplice. Apprezzo qualsiasi consiglio e, meglio ancora, link a tutorial e guide sia in italiano che in inglese.

Di nuovo grazie. ;)

Normalmente creo un nuovo progetto di tipo console, assegnando il nome, directory, ....
Poi, nella seconda schermata, quando viene chiesto l' "Application Type", seleziono DLL

Tubo Catodico
30-01-2014, 13:06
Normalmente creo un nuovo progetto di tipo console, assegnando il nome, directory, ....
Poi, nella seconda schermata, quando viene chiesto l' "Application Type", seleziono DLL

Sto trovando delle difficoltà nel far interagire labview ed opencv. Ho fatto una piccola DLL di prova che prende in ingresso due numeri, li somma, e li restituisce in uscita. Ha funzionato perfettamente, il problema giunge con open cv, in pratica scrivendo:
// opencv_32.cpp: definisce le funzioni esportate per l'applicazione DLL.
//

#include "stdafx.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>

using namespace cv;
using namespace std;


extern "C" __declspec(dllexport) void Gray(void)
{

const string ind = "C:\\Users\\sviluppo\\Desktop\\Tuli.bmp";
const string ind_2 = "C:\\Users\\sviluppo\\Desktop\\Tuli_Gray.bmp";
const string error = "Error";

Mat image;
Mat gray_img;
image = imread(ind, IMREAD_COLOR); // Read the file
cvtColor(image, gray_img, CV_BGR2GRAY);

if (!image.data) // Check for invalid input
{
cout << "Could not open or find the image" << std::endl;

}

namedWindow("Display window", WINDOW_AUTOSIZE); // Create a window for display.
imshow("Display window", image); // Show our image inside it.

namedWindow("Gray image", WINDOW_AUTOSIZE);
imshow("Gray image", gray_img);

imwrite(ind_2, gray_img);

waitKey(0); // Wait for a keystroke in the window


}

non riesco a far vedere a labview questa stupida funzione Gray...

sottovento
31-01-2014, 11:23
Hai gia' controllato i manuali, a riguardo? E' un bel po' che non uso 'ste cose, ma mi sembra strano che si possa creare una funzione qualsiasi in DLL, senza rispettare qualche convenzioni su
- nomi
- parametri delle funzioni
- modalita' di esportazione.

Per esempio, esportando i simboli come fai tu, (i.e. __declspec(dllexport) ), i vari nomi esportati dovrebbero essere decorati, sempre se non ricordo male.
"nomi decorati" significa che il compilatore cambia il nome aggiungendo delle stringhe di controllo, cosi' che il chiamante posso riconoscere i parametri da passare alla funzione, il loro tipo, il tipo di ritorno, ecc.

National Instruments raccomanda di leggere questi articoli:
http://zone.ni.com/reference/en-XX/help/371361F-01/lvhowto/callcodefromotherproglangs/
e
http://digital.ni.com/public.nsf/allkb/DCB90714981A1F148625731E00797C33

Hai avuto modo di consultarli? Purtroppo non posso farlo ora, ma spero che questo ti possa essere d'aiuto

Tubo Catodico
01-02-2014, 09:47
Hai avuto modo di consultarli? Purtroppo non posso farlo ora, ma spero che questo ti possa essere d'aiuto

Il secondo non lo avevo letto, grazie, appena ho mezz'ora libera a lavoro gli darò un'occhiata. Credo comunque che l'inghippo stia nell'header.

Tubo Catodico
03-02-2014, 16:05
Allora, continuo ad avere degli errori molto strani. Ho aggiornato la dll in header e cpp nel seguente modo:
#ifdef GENERICDLL_EXPORTS
#define GENERICDLL_API __declspec(dllexport)
#else
#define GENERICDLL_API __declspec(dllimport)
#endif

#include "stdafx.h"

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>

// Questa classe è esportata da Generic DLL.dll
class GENERICDLL_API CGenericDLL {
public:
int Summ(int a, int b);
int Sott(int a, int b);
int opencv(int a);
// TODO: aggiungere qui i metodi.
};


per l'header, mentre per quanto riguarda il file .cpp:

// Generic DLL.cpp: definisce le funzioni esportate per l'applicazione DLL.
//

#include "stdafx.h"
#include "Generic DLL.h"

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>

using namespace cv;
using namespace std;


// Esempio di variabile esportata
GENERICDLL_API int nGenericDLL=0;

// Funzioni esportate.
GENERICDLL_API int Summ(int a, int b)
{
return a+b;
}

GENERICDLL_API int Sott(int a, int b)
{
return a - b;
}

GENERICDLL_API int opencv(int a)
{
const string ind = "C:\\Users\\sviluppo\\Desktop\\Tuli.bmp";
const string ind_2 = "C:\\Users\\sviluppo\\Desktop\\Tuli_Gray.bmp";

//Mat image;


return 5;
}


Le funzioni implementate sono parecchio stupide e così come sono funzionano ed io riesco a richiamare la dll tramite labview. Il problema è che se mi liito solamente a togliere il commento alla linea "Mat image;" nel .cpp ricevo il seguente errore da labview:
The library specified for this node cannot be found or cannot be loaded. Right-click the Call Library Function node and select Configure, then choose the correct library name or path.

La cosa è un po' strana e sinceramente non so che pesci prendere...

sottovento
03-02-2014, 19:03
Le funzioni implementate sono parecchio stupide e così come sono funzionano ed io riesco a richiamare la dll tramite labview.

Ottimo! Mi sembra gia' un bel passo, no


The library specified for this node cannot be found or cannot be loaded. Right-click the Call Library Function node and select Configure, then choose the correct library name or path.

Diro' qualcosa di ovvio, ma dice che non riesce a trovare la libreria di OpenCV, oppure la libreria e' trovata ma non puo' essere caricata.

Per prima cosa, mi accerterei che la libreria sia trovata. Come sai, normalmente le librerie vengono cercate PRIMA nella directory di default (normalmente quella di lancio dell'applicazione) e poi nelle directory specificate nel PATH.
Hai verificato se le librerie di OpenCV (che presumo siano delle .dll, e' da un po' che preferisco JavaCV :D) siano nella directory corrente, oppure in una directory nel path? Immagino di si, ma e' meglio controllare, per sicurezza.

Nel caso la libreria sia trovata ma non viene caricata, controllerei prima la bitness, vale a dire che applicazione e librerie dovrebbero essere sempre tutte a 32 bit o 64, e che mischiare (per esempio, compilare l'applicazione a 32 bit mentre la dll e' a 64 bit) puo' far molto male.
Ti ricordo che Visual Studio compila per default a 32 bit, e devi seguire le istruzioni sparse per il web/msdn (scusami, la rete non funziona bene, qui) per farlo compilare a 64.

Se anche questo controllo e' ok, io lascerei labview in un angolo per qualche minuto e proverei a fare una piccola applicazione di tipo console (la piu' semplice) che carichi la tua libreria .dll, per vedere se da li' funziona o meno:
- se non funziona, probabilmente uno dei due casi di cui sopra non e' stato ben verificato. Ad ogni modo, puoi ottenere piu' informazioni e stamparle a schermo, e le prove sono piu' agevoli.
- se funziona.... beh, occorre cercare cos'e' cambiato, e se Labview accetta indifferentemente librerie 32/64

Fammi sapere. Buona notte

Tubo Catodico
04-02-2014, 08:39
Era un problema di questo tipo. Una volta inserita la mia DLL e le DLL di OpenCV nella cartella della VI di LabVIEW ha funzionato tutto. Non mi resta che aggiornare il PATH e vedere se tutto funziona ancora; comunque adesso ho capito il problema.

Grazie ancora sei stato essenziale! ;)