CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 13 of 13
  1. #1
    Join Date
    Jan 2005
    Posts
    35

    C++ Newbie - What have I done wrong?

    I am wanting to use the exported function "SendFax".

    When I call this function it returns 15, and nothing else happens.
    I have to admit defeat here.

    Please help.
    Code follows...

    Wee!
    Code:
    // The following ifdef block is the standard way of creating macros which make exporting 
    // from a DLL simpler. All files within this DLL are compiled with the ENZ_FAXING_EXPORTS
    // symbol defined on the command line. this symbol should not be defined on any project
    // that uses this DLL. This way any other project whose source files include this file see 
    // ENZ_FAXING_API functions as being imported from a DLL, wheras this DLL sees symbols
    // defined with this macro as being exported.
    
    #ifdef ENZ_FAXING_EXPORTS
    #define ENZ_FAXING_API __declspec(dllexport)
    #else
    #define ENZ_FAXING_API __declspec(dllimport)
    #endif
    
    // This class is exported from the ENZ_Faxing.dll
    class ENZ_FAXING_API CENZ_Faxing {
    public:
    	
    	CENZ_Faxing();
    
    	//properties
    	char* FaxNumber;
    
    	// TODO: add your methods here
    	char* SetFaxNumber(char* thisFaxNumber);
    	char* GetFaxNumber();
    };
    
    extern ENZ_FAXING_API int nENZ_Faxing;
    
    ENZ_FAXING_API int fnENZ_Faxing(void);
    
    
    
    
    // ENZ_Faxing.cpp : Defines the entry point for the DLL application.
    //
    
    #include "stdafx.h"
    #include "ENZ_Faxing.h"
    #include "winfax.h"
    #include "fstream.h"
    #include "stdio.h"
    
    
    BOOL APIENTRY DllMain( HANDLE 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;
    }
    
    // This is the constructor of a class that has been exported.
    // see ENZ_Faxing.h for the class definition
    CENZ_Faxing::CENZ_Faxing()
    { 
    	return; 
    }
    
    char* CENZ_Faxing::SetFaxNumber(char* thisFaxNumber)
    {
    	return thisFaxNumber;
    };
    
    char* CENZ_Faxing::GetFaxNumber()
    {
    	return FaxNumber;
    };
    
    ENZ_FAXING_API int SendFax(char* thisFaxNumber, int DEBUG)
    {
    		int retVal;
    		CENZ_Faxing FaxApp;	
    		FILE *thisFile;
    		char* output = "";
    		
    		if (DEBUG == 1) 
    		{
    			// Open a file for outputting debug information.
    			if ((thisFile = fopen("c:\\temp\\debug.log","r+")) == NULL)
    			{
    				return 20;
    			}
    			else
    			{
    				// Write to the file 
    				fprintf(thisFile, "FaxApp Object has been declared ok.\n" );
    			}
    		};
    		
    		if (FaxApp.FaxNumber == NULL)
    		{
    			FaxApp.FaxNumber = FaxApp.SetFaxNumber(thisFaxNumber);
    		};
    
    		if( DEBUG==1 )
    		{	// Write to the file 
    			fprintf(thisFile, "Fax number has been set ok\n");
    		};
    
    		FAX_PRINT_INFO fpi;
    		fpi.RecipientNumber = FaxApp.GetFaxNumber();
    		fpi.SizeOfStruct=sizeof(FAX_PRINT_INFO);
    
    		if(DEBUG==1)
    		{
    			// Write to the file 
    			fprintf(thisFile, "Process has initialised ok\n");
    		};
    
    		DWORD nJobID;
    		FAX_CONTEXT_INFO fci;
    		fci.SizeOfStruct=sizeof(FAX_CONTEXT_INFO);
    
    		retVal = FaxStartPrintJob(NULL,&fpi,&nJobID,&fci);
    
    		if (DEBUG==1)
    		{
    			fprintf(thisFile, "FaxStartPrintJob returned &d\n", retVal); 
    		};
    		
    		retVal = EndDoc(NULL);
    		
    		if (DEBUG==1)
    		{
    			fprintf(thisFile, "EndDoc returned %d\n",retVal);
    
    			//Close the file
    			fclose(thisFile);
    		}
    		return 1;
    }
    Last edited by Andreas Masur; February 6th, 2005 at 05:52 PM. Reason: Added code tags...

  2. #2
    Join Date
    Oct 2002
    Location
    Timisoara, Romania
    Posts
    14,360

    Re: C++ Newbie - What have I done wrong?

    First, please use the code tags when you post code.

    It seems that you can get a return error of 15 only from:
    Code:
    retVal = FaxStartPrintJob(NULL,&fpi,&nJobID,&fci);
    
    if (DEBUG==1)
    {
      fprintf(thisFile, "FaxStartPrintJob returned &d\n", retVal); 
    };
    
    retVal = EndDoc(NULL);
    Since EndDoc returns a value >0 if the function succeds, it is probably FaxStartPrintJob() that returns 15. Did you run it in debugger? That do you get in the log file especially from the print above?
    Marius Bancila
    Home Page
    My CodeGuru articles

    I do not offer technical support via PM or e-mail. Please use vbBulletin codes.

  3. #3
    Join Date
    Jan 2005
    Posts
    35

    Unhappy Re: C++ Newbie - What have I done wrong?

    I am slowly going nuts here.

    Having created a project to test this with <homer> doh1 </homer> the dll will not load into the test code at compile time.

    Compile error is:
    error C2564: 'int (char *,int)' : function-style conversion to builtin type takes only one argument
    Error executing cl.exe.

    Code snippet follows:

    Code:
    // TEST3.cpp : Defines the entry point for the application.
    //
    
    #include "stdafx.h"
    #include "resource.h"
    #include "stdio.h" 
    #include "windows.h"
    
    
    typedef int SendFax(char* FaxNumber,int Debug);
    
    #define MAX_LOADSTRING 100
    
    // Global Variables:
    HINSTANCE hInst;								// current instance
    TCHAR szTitle[MAX_LOADSTRING];								// The title bar text
    TCHAR szWindowClass[MAX_LOADSTRING];								// The title bar text
    
    // Foward declarations of functions included in this code module:
    ATOM				MyRegisterClass(HINSTANCE hInstance);
    BOOL				InitInstance(HINSTANCE, int);
    LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);
    
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
    {
     	// TODO: Place code here.
        HINSTANCE dllHandle = NULL;              
    	int retVal = 0;
    	int P;
    	
    	char* FaxNumber = "9520022";
    	dllHandle = LoadLibrary("ENZ_Faxing.dll");
    	GetProcAddress(dllHandle,"SendFax");
    	retVal = SendFax(FaxNumber , 1);
    Blah!

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: C++ Newbie - What have I done wrong?

    Quote Originally Posted by WeePecky
    I am slowly going nuts here.

    Having created a project to test this with <homer> doh1 </homer> the dll will not load into the test code at compile time.
    DLL's load at run-time, not compile time.
    Compile error is:
    error C2564: 'int (char *,int)' : function-style conversion to builtin type takes only one argument
    Now if you direct us to the line where this error is, maybe we can help you, but a lot of your program doesn't make sense:
    Code:
    typedef int SendFax(char* FaxNumber,int Debug);
    This is not correct. In all likelihood, you meant to do this:
    Code:
    typedef int (*SendFax)(char *, int);
    This is how you set up a typedef that defines a pointer to a function that returns an int and takes two arguments.
    Code:
    	GetProcAddress(dllHandle,"SendFax");
    	retVal = SendFax(FaxNumber , 1);
    This makes no sense. You are calling GetProcAddress, but what are you doing with the return value? Nothing.

    It is the return value of GetProcAddress that has the address of the SendFax function. You assign the return value to the function pointer, and then invoke the function using that point.
    Code:
            SendFax fn;
    	fn = (SendFax)GetProcAddress(dllHandle,"SendFax");
    	retVal = fn(FaxNumber , 1);
    The problem is that you're new to the language, but you've thrust yourself into trying to use somewhat advanced techniques such as function pointers without learning the basics of the language first.

    Regards,

    Paul McKenzie

  5. #5
    Join Date
    Jan 2005
    Posts
    35

    Re: C++ Newbie - What have I done wrong?

    Thanks Paul.

    No arguments from me re being a newbie.
    It's about 6 years since I have used c/c++ in any form.

    I have managed to compile so thanks for your help!

    Wee!

  6. #6
    Join Date
    Jan 2005
    Posts
    35

    Smile Re: C++ Newbie - What have I done wrong?

    Getting closer,

    I have managed to load the dll and the debugger runs to the call to FaxStartPrintJob.

    I have simplified the code in the dll quite a bit.

    Code:
    ENZ_FAXING_API int SendFax(char* thisFaxNumber)
    {
    		int retVal;
    
    		FAX_PRINT_INFO fpi;
    		fpi.RecipientNumber = thisFaxNumber;
    		fpi.SizeOfStruct=sizeof(FAX_PRINT_INFO);
    
    		DWORD nJobID;
    		FAX_CONTEXT_INFO fci;
    		fci.SizeOfStruct=sizeof(FAX_CONTEXT_INFO);
    
    		
    		retVal = FaxStartPrintJob(NULL,&fpi,&nJobID,&fci);
    
    
    		retVal = EndDoc(fci.hDC);
    		return retVal;
    }
    When execution reaches FaxStartPrintJob get the following error:

    First-chance exception in TEST3.exe (KERNEL32.DLL): 0xC0000005: Access Violation.

    From reading through the forum posts this may have nothing to do with the code I have written. Is this so? If so, what could the resolution be?

    Thanks in anticipation.
    Wee!

  7. #7
    Join Date
    Apr 1999
    Posts
    27,449

    Re: C++ Newbie - What have I done wrong?

    Quote Originally Posted by WeePecky
    Getting closer,

    I have managed to load the dll and the debugger runs to the call to FaxStartPrintJob.
    When execution reaches FaxStartPrintJob get the following error:

    First-chance exception in TEST3.exe (KERNEL32.DLL): 0xC0000005: Access Violation.

    From reading through the forum posts this may have nothing to do with the code I have written. Is this so? If so, what could the resolution be?
    Please post a small, complete example. We don't know exactly what you are doing since you didn't post all of the calls necessary to even duplicate your error. Have you tried a very simple example?

    For example:
    Code:
    #include <whatever necessary headers>
    
    int main()
    {
        (Set up the fax)
        (Print the fax)
        (Close the fax)
    }
    I've never used the Fax API, however, if I were to use it, I would always code the simplest example with hard-coded values (values I know will or should work -- no "computed" file names or anything like that). The reason is that I would need to know exactly how to use it in a larger, more complex application without introducing possible coding bugs that have nothing to do with the API itself.

    Regards,

    Paul McKenzie

  8. #8
    Join Date
    Jan 2005
    Posts
    35

    Re: C++ Newbie - What have I done wrong?

    Hi Paul,

    The values are all hard coded and translate ok.
    Very simple.

    I have used a "Typical Hello World" application and added to the code in the //TODO of the WinMain function. The Call works fine and I can step throug to the dll's code...

    Code:
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
    {
                   // TODO: Place code here.
    	char *FaxNumber = "9520022";
    	SendFax fn;
    	dllHandle = LoadLibrary("ENZ_Faxing.dll");
    
                   \\exported table shows function is called ?SendFax@@YAHPAD@Z
    	fn = (SendFax)GetProcAddress(dllHandle,"?SendFax@@YAHPAD@Z");
    	retVal = fn(FaxNumber);
    
                   code continues....
    The dll code is:

    Code:
    include "stdafx.h"
    #include "ENZ_Faxing.h"
    #include "windows.h"
    #include "winfax.h"
    #include "fstream.h"
    #include "stdio.h"
    
    
    BOOL APIENTRY DllMain( HANDLE 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;
    }
    
    
    ENZ_FAXING_API int SendFax(char* thisFaxNumber)
    {
    		int retVal;
    	
    		FAX_PRINT_INFO fpi;
    		fpi.RecipientNumber = thisFaxNumber;
    		fpi.SizeOfStruct=sizeof(FAX_PRINT_INFO);
    
    		DWORD nJobID;
    		FAX_CONTEXT_INFO fci;
    		fci.SizeOfStruct=sizeof(FAX_CONTEXT_INFO);
    
    		\\falls over on the following call...
    		retVal = FaxStartPrintJob(NULL,&fpi,&nJobID,&fci);
    
    		retVal = EndDoc(fci.hDC);
    		return retVal;
    }
    When I call this from a non c/c++ (VB) application function returns 15.

    I hope this is enough for you to follow.
    Thanks for your help.

    Wee!

  9. #9
    Join Date
    Apr 1999
    Posts
    27,449

    Re: C++ Newbie - What have I done wrong?

    There are too many things that are of concern.

    1) Do not try a DLL first. Write a normal C or C++ application that uses the FAX API. Verify that it works (sends the fax).

    2) Once you have completed 1), then you should get a good knowledge on how to write DLL's properly in terms of exporting functions.

    3) What is ENZ_FAXING_API? Remember, we don't have any of your code except what you post.

    4) How is this called in VB? You must send a null-terminated string, not a VB String.

    Anyway, your DLL is written incorrectly (or kludgely) for a VB program to use. First, the signature of an exported function should be _stdcall. Second, the function should be extern "C". Then use a DEF file to get rid of all the decoration in the name. Your "SendFax" has got that C++ decoration in the name -- get rid of it by doing what I've stated.

    If you don't know this, then I recommend you see the CodeGuru FAQ on writing DLL's that will be called from non-C and C++ languages (I don't have the link, even though I wrote it, sorry).

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; February 7th, 2005 at 10:47 PM.

  10. #10
    Join Date
    Jan 2005
    Posts
    35

    Re: C++ Newbie - What have I done wrong?

    Noted with thanks
    Will start again.
    Cheers

  11. #11
    Join Date
    Apr 1999
    Posts
    27,449

    Re: C++ Newbie - What have I done wrong?

    Link to FAQ:

    http://www.codeguru.com/forum/showth...hreadid=231254

    Regards,

    Paul McKenzie

  12. #12
    Join Date
    Jan 2005
    Posts
    35

    Re: C++ Newbie - What have I done wrong?

    Hello again,

    Thanks for your previous help.
    I have the method FaxStartPrintJob behaving nicely, and the export is much more friendly!

    I have one more question, because while the above method works ok, I am not sure what is required to print the actual document to the fax.

    I have all the code, proven to work in samples, but when I try to complie it tells me that the Identifyer is undeclarred. While the problem is obvious - I am missing either a header file or lib entry, I cannot find which one I should be including to make this work.

    An example of the problem is:

    Code:
    ...
    
    		//Print the document
    		CDC dc;
    		dc.Attach(fci.hDC);
    		OnDraw(&dc);	
    ...
    I have the function "OnDraw" defined elsewhere.

    Compiler says:
    C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO\MYPROJECTS\FAXING\ENZ_WinFax\ENZ_WinFax.cpp(64) : error C2065: 'CDC' : undeclared identifier
    C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO\MYPROJECTS\FAXING\ENZ_WinFax\ENZ_WinFax.cpp(64) : error C2146: syntax error : missing ';' before identifier 'dc'
    C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO\MYPROJECTS\FAXING\ENZ_WinFax\ENZ_WinFax.cpp(64) : error C2065: 'dc' : undeclared identifier

    I am not using the MFC's which could be another clue(??).

    Any help appreciated.

    Cheers
    Wee!
    Last edited by WeePecky; February 23rd, 2005 at 03:16 PM.

  13. #13
    Join Date
    Apr 1999
    Posts
    27,449

    Re: C++ Newbie - What have I done wrong?

    Quote Originally Posted by WeePecky
    Hello again,
    I am not using the MFC's which could be another clue(??).
    That's the reason for the error. Those classes are MFC classes. Get samples that work with the API, not MFC (there are tons of samples that show how to print a document from a Windows API program).

    Regards,

    Paul McKenzie

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured