Solved

Console program in C to DLL

Posted on 2010-11-18
7
599 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
7 Comments
 
LVL 31

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 31

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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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 31

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 31

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

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
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.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.

724 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