|
-
February 6th, 2005, 05:06 PM
#1
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...
-
February 6th, 2005, 05:21 PM
#2
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?
-
February 7th, 2005, 03:34 PM
#3
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!
-
February 7th, 2005, 04:32 PM
#4
Re: C++ Newbie - What have I done wrong?
 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
-
February 7th, 2005, 04:50 PM
#5
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!
-
February 7th, 2005, 09:59 PM
#6
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!
-
February 7th, 2005, 10:15 PM
#7
Re: C++ Newbie - What have I done wrong?
 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
-
February 7th, 2005, 10:32 PM
#8
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!
-
February 7th, 2005, 10:43 PM
#9
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.
-
February 7th, 2005, 10:48 PM
#10
Re: C++ Newbie - What have I done wrong?
Noted with thanks
Will start again.
Cheers
-
February 7th, 2005, 10:51 PM
#11
Re: C++ Newbie - What have I done wrong?
-
February 23rd, 2005, 02:53 PM
#12
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.
-
February 23rd, 2005, 03:48 PM
#13
Re: C++ Newbie - What have I done wrong?
 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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|