|
Apologies for the shouting but this is important.
When answering a question please:
- Read the question carefully
- Understand that English isn't everyone's first language so be lenient of bad spelling and grammar
- If a question is poorly phrased then either ask for clarification, ignore it, or mark it down. Insults are not welcome
- If the question is inappropriate then click the 'vote to remove message' button
Insults, slap-downs and sarcasm aren't welcome. Let's work to help developers, not make them feel stupid.
cheers,
Chris Maunder
The Code Project Co-founder
Microsoft C++ MVP
|
|
|
|
|
For those new to message boards please try to follow a few simple rules when posting your question.- Choose the correct forum for your message. Posting a VB.NET question in the C++ forum will end in tears.
- Be specific! Don't ask "can someone send me the code to create an application that does 'X'. Pinpoint exactly what it is you need help with.
- Keep the subject line brief, but descriptive. eg "File Serialization problem"
- Keep the question as brief as possible. If you have to include code, include the smallest snippet of code you can.
- Be careful when including code that you haven't made a typo. Typing mistakes can become the focal point instead of the actual question you asked.
- Do not remove or empty a message if others have replied. Keep the thread intact and available for others to search and read. If your problem was answered then edit your message and add "[Solved]" to the subject line of the original post, and cast an approval vote to the one or several answers that really helped you.
- If you are posting source code with your question, place it inside <pre></pre> tags. We advise you also check the "Encode HTML tags when pasting" checkbox before pasting anything inside the PRE block, and make sure "Ignore HTML tags in this message" check box is unchecked.
- Be courteous and DON'T SHOUT. Everyone here helps because they enjoy helping others, not because it's their job.
- Please do not post links to your question in one forum from another, unrelated forum (such as the lounge). It will be deleted.
- Do not be abusive, offensive, inappropriate or harass anyone on the boards. Doing so will get you kicked off and banned. Play nice.
- If you have a school or university assignment, assume that your teacher or lecturer is also reading these forums.
- No advertising or soliciting.
- We reserve the right to move your posts to a more appropriate forum or to delete anything deemed inappropriate or illegal.
cheers,
Chris Maunder
The Code Project Co-founder
Microsoft C++ MVP
|
|
|
|
|
Hi!
I try to implement a callback function within a dll, which triggers an assigned function in the main application. I want to trigger this "event" in the main app from within the dll.
Here is my code from the dll:
extern "C" __declspec(dllexport) void funcA(const unsigned long long a, const unsigned long long b);
extern "C"
{
typedef void(__stdcall* callback_t)(unsigned int halfbeast);
__declspec(dllexport) void public_func_taking_callback(callback_t evHnd)
{
evHnd(333);
}
}
void funcA(
const unsigned long long a,
const unsigned long long b)
{
if(a>10)
callback_t(public_func_taking_callback);
}
Here is the code I use in the main application to load the library and attach to the functions:
typedef void (__stdcall *eventCallback)(unsigned int miau);
typedef void (__stdcall *setCallback)(eventCallback evHnd);
void __stdcall CallB(unsigned int);
void __fastcall TForm1::Button1Click(TObject *Sender)
{
signed int retval;
unsigned int i;
char txt[7];
unsigned long long a,index;
UnicodeString USt;
HINSTANCE dllHandle=NULL;
dllHandle = LoadLibrary(L"test.dll");
if (!dllHandle){
ShowMessage("Could not load test.dll");
Form1->Close();
}
else{
void (__stdcall* funcA)(const unsigned long long a, const unsigned long long b);
funcA=(void(__stdcall*)(const unsigned long long a, const unsigned long long b))GetProcAddress(dllHandle,"funcA");
setCallback values=(setCallback)GetProcAddress(dllHandle, "public_func_taking_callback");
if(values != NULL){
values(&CallB);
}
if(!funcA){
Memo1->Text="No handle to function found.";
}
else{
funcA(1,1);
funcA(100,100);
}
FreeLibrary(dllHandle);
}
}
void __stdcall CallB(unsigned int halfbeast){
ShowMessage("triggered");
}
What happens is unfortunately not what I wanted:
1) In the very moment the line "values(&CallB);" is executed, CallB is called. This is not what I wanted, I justed wanted to give the callback pointer of the dll to my function CallB.
2) CallB is not called when the line "funcA(100,100);" is executed. Most likely there is something wrong with the function call within the dll, but I cannot see it...
|
|
|
|
|
1. That is correct. At that point, values is set to public_func_taking_callback , which takes the address of a function and immediately calls it.
2. funcA calls callback_t , but callback_t has never been set to any value.
To be honest, I find it difficult to understand your code, so I may have still missed something. However, you should be able to see the exact sequence of events by running the code in the debugger.
|
|
|
|
|
Hi Richard,
thanks for the answers. Yes I can debug it, but it doesn't help me much, since I don't understand why it behaves that way.
1.) OK, got it. Unfortunately then I do not know, how I pass the address of the function of CallB to the dll. I want the dll to call CallB() in the moment callback_t is called.
Most likely I confuse here something, but I find it very hard to understand the syntax. It seems even harder since it is wrong
I wasn't able to find any C++ examples for that.
2.) I thought I set it to public_func_taking_callback, but obviously this is not the case.
Maybe I should explain again, what I try to do:
In my main application I want to declare a function. This function should be registered in the dll as a callback function. When during run time in the dll some criteria match ( if(a>10) ) the dll should call the function in the main application and execute it.
|
|
|
|
|
Bodo2407 wrote: I don't understand why it behaves that way. It behaves that way because that is the way you have written the code.
1. So you need to change the code in public_func_taking_callback as follows:
__declspec(dllexport) void public_func_taking_callback(callback_t evHnd)
{
callback_t = evHnd;
}
And you need to change funcA to:
if(a>10)
callback_t(a);
Again, make these changes and then step through the code in the debugger to check that it is correct.
|
|
|
|
|
Hi Richard,
thanks a lot, but unfortunately it cannot compile:
__declspec(dllexport) void public_func_taking_callback(callback_t evHnd)
{
callback_t = evHnd;
}
Failure given:
-Error C2513 'void (__stdcall *)(unsigned int)': no variable declared before '='
So the typedef earlier doesn't work or... ?
|
|
|
|
|
callback_t is a type, not a function.
In your DLL , you do need a variable of such a type, in order to store the user function address.
Something similar to (not tested)
typedef void (__stdcall* callback_t) (unsigned int halfbeast);
static callback_t s_user_function = nullptr;
extern "C" __declspec(dllexport) void funcA(const unsigned long long a, const unsigned long long b);
extern "C"
{
__declspec(dllexport) void public_func_taking_callback(callback_t evHnd)
{
s_user_function = evHnd;
}
}
void funcA(
const unsigned long long a,
const unsigned long long b)
{
if(a>10 && s_user_function != nullptr)
s_user_function(333);
}
"In testa che avete, Signor di Ceprano?"
-- Rigoletto
|
|
|
|
|
Problem 1 — Flawed MAC designs (11 marks) For this problem, you need to carefully trace through the given MAC algorithms, and
|
|
|
|
|
No idea what that is supposed to be. Maybe you lost connection while typing.
|
|
|
|
|
You never asked a question, but based on what other people are doing lately, it seems you're just trying to post your homework assignment from Chegg Study, thinking someone is going to write the code for you.
That's not going to happen.
|
|
|
|
|
Copy off of the guy sitting next to you. It's your only hope.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
Hi
I have a C DLL that processes data for a MFC C++ program. It happens to be my FTP folder where files are received from FTP. when I step thru the code under the VS debugger everything runs fine
I make a breakpoint in the MFC code and when after getting the ProcAddress I go into the function.
So how do I know what the problem is when I don't run under the VS debugger, well I have a SEH (handler that pops up with a messagebox and I attach the debugger and observe the rc from _sopen_s that fails)
I decided to put a MessageBox in when it fails (in the DLL) and upon entry to the DLL as well, in the hope that I can then attach the debugger and get a better idea but the messagebox fails to appear I do re-link the MFC program as well
I went as far a deleting the .lib TO ensure I was picking it up while linking the MFC program and I got a link error so I know its picking the .lib of the DLL
I am running both the (VS Debugger and the MFC program in administrator mode)
|
|
|
|
|
Well it could be any one of a million things, but without more information it is pointless trying to guess. Also deleting the .lib file does not guarantee that you are loading the correct .dll at execution time. You should start by rebuilding everything from clean to ensure that no component is out of sync. Secondly, and much more importantly, where does the EACCESS * error occur, and what is the code trying to do at that point?
*EACCESS is returned (most often) when trying to access some file/directory that is protected. And even when running in admin mode some things remain blocked.
|
|
|
|
|
The EACCESS occurs on _sopen_s the only thing I can think of regarding that is that I have the path + filename and maybe the open function only takes a file name
Regardless I’m gong you’re-build the DLL thanks
|
|
|
|
|
What exactly are you trying to open, and what sharing options are you using?
Quote: EACCES The given path is a directory, or the file is read-only, but an open-for-writing operation was attempted.
|
|
|
|
|
It’s a mainframe z/os sysadata file which is a binary representation of Z/OS Assembler program listing I have all the big endian conversion routines for going from mainframe to pc it did work as I was able to display the listing in the richedit that called the DLL and processed this file thanks
|
|
|
|
|
I have a code:
template <typename Func, typename... Args>
auto Add(Func&& f, Args&&... args)
{
using RetType = std::invoke_result_t<Func, Args...>;
and on last line, at compiling time I got:
error C7510: 'invoke_result_t': use of dependent type name must be prefixed with 'typename'
How can I overcome this error ?
|
|
|
|
|
I believe that typename is supposed the be prefixed to tell the compiler that invoke_result_t is defining a type:
using RetType = std::typename invoke_result_t<Func, Args...>;
|
|
|
|
|
I have tried:
using RetType = std::typename invoke_result_t<Func, Args...>;
but I got:
error C2589: 'typename': illegal token on right side of '::'
|
|
|
|
|
Try moving it to the front:
using RetType = typename std::invoke_result_t<Func, Args...>; This[^] may be of help.
|
|
|
|
|
I already did:
using RetType = typename std::invoke_result_t<Func, Args...>;
Result:
error C2760: syntax error: unexpected token '<', expected ';'
|
|
|
|
|
See "Helper types" on this page[^]. It looks like invoke_result_t is itself a type alias. Try std::invoke_result without the _t .
|
|
|
|
|
|
CString isWrong = _T(" is wrong");
CString andMsg = _T(" and ");
bool bCorrect[4];
int numOfFalse = 0;
for(int i=0; i<4; i++){
bCorrect[i] = true;
if(arrA[i] != arrB[i]){
bCorrect[i] = false;
numOfFalse++;
}
}
for(int i=0; i<4; i++){
if((bCorrect[i] == false) && (numOfFalse == 2))
{
strRslt.Format("Q%d", i+1);
m_listRslt.AddString(strRslt + isWrong);
}
}
I want to print out something like Q1 and Q2 is wrong. Can anyone teach me ?
|
|
|
|