Solved

Console program in C to DLL

Posted on 2010-11-18
7
581 Views
Last Modified: 2012-08-13
Hello experts,

This is my second approach to this question.

I use VC++ 2008 Pro.

I have a program from the book. It compiles fine and creates console application.

Please have a look at the attachement.

I would like to make a dll from it to be able to use it in other applications.

I am trying to use an example of how to make dll files:

So I have three files.

***1***
DLL_Tutorial.h

#ifndef MY_HEADER
#define MY_HEADER

#define DECLDIR __declspec(dllexport)

extern "C"
{
    DECLDIR int Add( int a, int b );
    DECLDIR void Function( void );
}

#endif

***2***
def.def

LIBRARY dll_tutorial

DESCRIPTION "our simple DLL"

EXPORTS
   Add @1
   Function @2

***3***
DLL_Tutorial.cpp

#include <iostream>
#define DLL_EXPORT
#include "dll_tutorial.h"

{
 DECLDIR int Add( int a, int b )  {
  return( a + b );
 }

 DECLDIR void Function( void )
 {
  std::cout << "DLL Called!" << std::endl;
 }
}


This dll compiles fine and works.

Now I try to make a really useful dll.


I add attached file to "Source Files", trying to compile it and I get lots of errors like:


ch8_ex8_3.obj : error LNK2019: unresolved external symbol _cvReleaseImage
referenced in function "int __cdecl main2(int,char * * const)"
(?main2@@YAHHQAPAD@Z)
ch8_ex8_3.obj : error LNK2019: unresolved external symbol _cvDestroyWindow
referenced in function "int __cdecl main2(int,char * * const)"
(?main2@@YAHHQAPAD@Z)
ch8_ex8_3.obj : error LNK2019: unresolved external symbol _cvWaitKey
referenced in function "int __cdecl main2(int,char * * const)"
(?main2@@YAHHQAPAD@Z)


Question:

How can I do it?

thank you

panJames  ch8-ex8-3.cpp ch8-ex8-3.cpp
//  Example 8-3. Finding and drawing contours on an input image

#include <cv.h>

#include <highgui.h>

#include <stdio.h>



//Some defines we left out of the book 

#define CVX_RED		CV_RGB(0xff,0x00,0x00)  

#define CVX_GREEN	CV_RGB(0x00,0xff,0x00)

#define CVX_BLUE	CV_RGB(0x00,0x00,0xff)



int main(int argc, char* argv[]) {



  cvNamedWindow( argv[0], 1 );

  IplImage* img_8uc1 = NULL;

  

  //Changed this a little for safer image loading and help if not

  if( argc != 2 || !(img_8uc1 = cvLoadImage( argv[1], CV_LOAD_IMAGE_GRAYSCALE )) ){

  printf("\nExample 8_3 Drawing Contours\nCall is:\n./ch8_ex8_3 image\n\n");

  return -1;}

  

  

  IplImage* img_edge = cvCreateImage( cvGetSize(img_8uc1), 8, 1 );

  IplImage* img_8uc3 = cvCreateImage( cvGetSize(img_8uc1), 8, 3 );



  cvThreshold( img_8uc1, img_edge, 128, 255, CV_THRESH_BINARY );

  CvMemStorage* storage = cvCreateMemStorage();



  CvSeq* first_contour = NULL;



  int Nc = cvFindContours(

     img_edge,

     storage,

     &first_contour,

     sizeof(CvContour),

     CV_RETR_LIST // Try all four values and see what happens

  );



  int n=0,k;

  printf("\n\nHit any key to draw the next contour, ESC to quit\n\n");

  printf( "Total Contours Detected: %d\n", Nc );



  for( CvSeq* c=first_contour; c!=NULL; c=c->h_next ) {

     cvCvtColor( img_8uc1, img_8uc3, CV_GRAY2BGR );

     cvDrawContours(

        img_8uc3,

        c,

        CVX_RED,  //Yarg, these are defined above, but not in the book.  Oops

        CVX_BLUE,

        0,        // Try different values of max_level, and see what happens

        2,

        8

     );



     printf("Contour #%d\n", n );

     cvShowImage( argv[0], img_8uc3 );

     printf(" %d elements:\n", c->total );

     for( int i=0; i<c->total; ++i ) {

     CvPoint* p = CV_GET_SEQ_ELEM( CvPoint, c, i );

        printf("    (%d,%d)\n", p->x, p->y );

     }



     if((k = cvWaitKey()&0x7F) == 27)

       break;

     n++;

  }



  printf("Finished all contours. Hit key to finish\n");



  cvCvtColor( img_8uc1, img_8uc3, CV_GRAY2BGR );

  cvShowImage( argv[0], img_8uc3 );

  cvWaitKey(0);

  cvDestroyWindow( argv[0] );

  cvReleaseImage( &img_8uc1 );

  cvReleaseImage( &img_8uc3 );

  cvReleaseImage( &img_edge );

  return 0;



}

Open in new window

0
Comment
Question by:panJames
  • 4
  • 3
7 Comments
 
LVL 30

Expert Comment

by:Zoppo
ID: 34162773
Hi panJames,

IMO you need to tell the DLL project to link to the OpenCV library (I never used it so I unfortunateley don't know it's exact name).

Depending on compiler/OS you can either set this in the poject-/make-file or, i.e. in MS VisualStudio, tell the linker to use it by a '#pragma comment( lib, "<name of the lib>" );

Anyway if not alreay done the OpenCV library path has to be added to the LibPath the linker uses.

Hope that helps,

ZOPPO
0
 

Author Comment

by:panJames
ID: 34163121
Added file names to Linker options. It compiles now.

I checked created dll, it exports my main2 function.

I try to use it so I created test program:

***

#pragma comment(lib, "source.lib")

#include <iostream>

#include "C:\Documents and Settings\pan.james\My Documents\Visual Studio 2008\Projects\DLL\source\source\source\dll_tutorial.h"

int main()
{
      char * argument[2];

      std::cout << Add(23, 43) << std::endl; // call and print the result of Add() from DLL
      Function();     // call Function() from DLL

      argument[0] = "";
      argument[1] = "";
      main2(2, argument);


      std::cin.get(); // Wait for input to prevent opening then closing immediately

      return(1); // return success
}

It does not compile.

I get error:

dll_test_implicit.obj : error LNK2019: unresolved external symbol _main2 referenced in function _main


panJames
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34163155
Hm - how did you declare the 'main2' for export/import? For implicit use (as you use it in your EXE) you have to add it in the header in the 'extern "C" ...' block similar to the functions 'Add' and 'Function', also prefixed with 'DECLDIR'. If you want to be able to load the function using 'LoadLibrary' and 'GetProcAddress' you also have to add it in the .DEF file.
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:panJames
ID: 34163185
Please have a look at the code below.
#include <cv.h>

#include <highgui.h>

#include <stdio.h>



//Some defines we left out of the book 

#define CVX_RED		CV_RGB(0xff,0x00,0x00)  

#define CVX_GREEN	CV_RGB(0x00,0xff,0x00)

#define CVX_BLUE	CV_RGB(0x00,0x00,0xff)



#include <iostream> // Access to std::cout and std::endl

#define DLL_EXPORT  // DECLDIR will perform an export for us

#include "dll_tutorial.h" // Include our header, must come after #define DLL_EXPORT





//  Example 8-3. Finding and drawing contours on an input image

extern "C" // Get rid of name mangeling





DECLDIR int main2(int argc, char* argv[]) {



  cvNamedWindow( argv[0], 1 );

  IplImage* img_8uc1 = NULL; 

  

  //Changed this a little for safer image loading and help if not

  if( argc != 2 || !(img_8uc1 = cvLoadImage( argv[1], CV_LOAD_IMAGE_GRAYSCALE )) ){

	printf("\nExample 8_3 Drawing Contours\nCall is:\n./ch8_ex8_3 image\n\n");



	return -1;



  }



  IplImage* img_edge = cvCreateImage( cvGetSize(img_8uc1), 8, 1 ); 

  IplImage* img_8uc3 = cvCreateImage( cvGetSize(img_8uc1), 8, 3 ); 



  cvThreshold( img_8uc1, img_edge, 128, 255, CV_THRESH_BINARY );   

  CvMemStorage* storage = cvCreateMemStorage();



  CvSeq* first_contour = NULL;



  int Nc = cvFindContours(

     img_edge,

     storage,

     &first_contour,

     sizeof(CvContour),

     1 // Try all four values and see what happens

  );



  /*

	#define CV_RETR_EXTERNAL 0

	#define CV_RETR_LIST     1

	#define CV_RETR_CCOMP    2

	#define CV_RETR_TREE     3



  */



  int n=0,k;

  printf("\n\nHit any key to draw the next contour, ESC to quit\n\n");

  printf( "Total Contours Detected: %d\n", Nc );



  for( CvSeq* c=first_contour; c!=NULL; c=c->h_next ) {

     cvCvtColor( img_8uc1, img_8uc3, CV_GRAY2BGR );



	 if (c->total > 100)

	 {

		 cvDrawContours(

			img_8uc3,

			c,

			CVX_RED,  //Yarg, these are defined above, but not in the book.  Oops

			CVX_BLUE,

			0,        // Try different values of max_level, and see what happens

			2,

			8

		 );



		 printf("Contour #%d\n", n );

		 cvShowImage( argv[0], img_8uc3 );  

		 printf(" %d elements:\n", c->total );



		 for( int i=0; i<c->total; ++i ) {

			CvPoint* p = CV_GET_SEQ_ELEM( CvPoint, c, i );

			printf("    (%d,%d)\n", p->x, p->y );



		 }



		if((k = cvWaitKey()&0x7F) == 27)

			break;



	 }



     n++;

  }



  printf("Finished all contours. Hit key to finish\n");



  cvCvtColor( img_8uc1, img_8uc3, CV_GRAY2BGR );

  cvShowImage( argv[0], img_8uc3 );

  cvWaitKey(0);



  cvDestroyWindow( argv[0] );

  cvReleaseImage( &img_8uc1 );

  cvReleaseImage( &img_8uc3 );

  cvReleaseImage( &img_edge );



  return 0;



}

Open in new window

0
 
LVL 30

Accepted Solution

by:
Zoppo earned 500 total points
ID: 34163243
You have to declare it in the header 'DLL_Tutorial.h' - further I forgot to mention that in that header the 'DECLDIR' should be declared differently when used in the DLL or in the EXE project - therefor you should declare a preprocessor define in the projects C++->Preprocessor settings of the DLL project like 'MY_DLL_EXPORTS' - then use this define to declare the functions as 'dllexport' when building the DLL and as 'dllimport' when using thew header in the EXE.

So the relevant part of the header should look somehow like this:

> #ifdef MY_DLL_EXPORTS
> #define DECLDIR __declspec(dllexport)
> #else
> #define DECLDIR __declspec(dllimport)
> #endif
> extern "C"
> {
>    DECLDIR int Add( int a, int b );
>    DECLDIR void Function( void );
>    DECLDIR int main2(int argc, char* argv[]);
> }
0
 

Author Comment

by:panJames
ID: 34164196
Thank you mate!

You really helped me!

panJames
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34164720
Fine, you're welcome - I'm glad I could help ...

Have a nice day,

best regards,

ZOPPO
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now