Multithreading with _beginthread in C++/CLI - multithreading

I'm having a problem with _beginthread in microsoft visual studio c++ 10 express:
my code:
void __cdecl DashThread( void * Args ) // function without any class refs
{
while(1){
MessageBox::Show("work");
Sleep(5000);
}
_endthread();
}
private:
System::Void button8_Click_1(System::Object^ sender, System::EventArgs^ e) {
HANDLE HDash = ( HANDLE ) _beginthread(DashThread, 0, NULL );
}
and errors:
error C3641: 'DashThread' : invalid calling convention '__cdecl ' for function compiled with /clr:pure or /clr:safe
error C2664: 'beginthread' : cannot convert parameter 1 from 'void (_cdecl *)(void *)' to 'void (__cdecl *)(void *)'

From the compiler error it seems you are compiling your project with /clr:pure or /clr:safe (in which case you are not programming in C++, but C++/CLI by the way) and thus cannot use the __cdecl calling convention, which is in turn required by _beginthread.
If you are programming in C++/CLI (and thus .NET) anyway, then why not just use .NET's threading facilities instead of the strange pseudo-standard-Win32-wrapper _beginthread?
If you want to use C++/CLI, but still be able to use good old _beginthread, then try to compile it with just /clr instead of /clr:pure, which allows non-managed functions that can have __cdecl calling convention.

Try to buid your program with /clr instead of /clr:pure.
See http://msdn.microsoft.com/en-us/library/k8d11d4s.aspx

Related

unresolved external symbol referenced in function removed by /OPT:REF

I have a function bar() that I don't actually call, that calls unimplemented foo():
void foo();
void bar()
{
foo();
}
int main()
{
}
If I package each function in a separate section/COMDAT and ask the linker to remove unused sections/COMDAT, I can get gcc to compile the program
gcc -ffunction-sections -Xlinker --gc-sections LinkerFunctions.cpp
but the equivalent in Visual C++ 2019
cl /Gy LinkerFunctions.cpp /link /OPT:REF
barks that
error LNK2019: unresolved external symbol "void __cdecl foo(void)" (?foo##YAXXZ) referenced in function "void __cdecl bar(void)" (?bar##YAXXZ)
How can I get msvc to compile the program?
Got your example working by adding inline, even after adding __declspec(noinline) to prevent actual inlining.
void foo();
__declspec(noinline)
inline void bar()
{
foo();
}
int main()
{
}
Tried because the documentation says:
Inlined functions and member functions defined inside a class declaration are always COMDATs.
Not sure however if it is robust solution, or works just in this particular case.
Accidentally found a linker switch for that:
cl incomplete.cpp /link /FORCE:UNRESOLVED
Will give a warning but in fact will work.

warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)

This particular warning, generated on compiling my vc++ code in VS 2008 is bugging me for a while. On going through related posts in SO and in microsoft forums for this warning, It is advised to disable the warning using pragma warning, But is there a way to fix this issue without a warning pragma?
class CBLockException : public CBException
{
public:
// Constructor
CBLockException();
CBLockException(const char *tag);
CBLockException(const char *func, const char *tag, const char *msg = NULL);
};
class CLASS_DECL_BASEOBJECTS CBLock : public CBObject
{
public:
enum Locktype { READLOCK, WRITELOCK };
CBLock() throw (CBLockException*); // C4290
virtual ~CBLock();
void Lock(Locktype lockType = WRITELOCK);
void Unlock(Locktype lockType = WRITELOCK);
private:
class LockImplementation;
LockImplementation *lockImp;
};
class CBLock::LockImplementation
{
public:
LockImplementation() throw (CBLockException*); //C4290
~LockImplementation();
CRITICAL_SECTION csExclusive;
CRITICAL_SECTION csReader;
HANDLE hevReadDone;
int cReader;
};
But is there a way to fix this issue without a warning pragma?
Yes. Delete the throw specification. It does not do what you think it does. Instead, it is mostly useless.
Specifically, writing:
CBLock() throw (CBLockException*);
…
CBLock::CBLock() { /* … */ }
is essentially equivalent to
CBLock();
…
CBLock::CBLock() {
try {
/* … */
} catch(CBLockException*&) { // Yes, like this! Stop throwing exceptions by pointer, please!
throw;
} catch(...) {
throw std::bad_exception();
}
}
(actually, with constructor it will be equivalent to the function try block, but I don't want to complicate it further with yet another C++ wart)
In particular, notice it does not actually check that the block is not throwing any other kind of exception. The only thing it does is convert any other exception to a totally useless std::bad_exception, throwing any useful information away in the process.
The recommended fix is to convert any throw declarations to documentation comments!
Also note that this applies even to the throw() specification. The only useful thing is the nothrow specification introduced in C++11, which actually checks the function won't throw any C++ exception, ever, and it's earlier MSC++-specific __declspec(nothrow) equivalent.
Go to project Property Pages -> Configuration Properties -> C/C++ -> Advanced -> Disable Specific Warnings -> Edit
Enter codes of warnings to be disabled separated by semicolon (in your case 4290 without the leading "C")
Source: http://msdn.microsoft.com/en-us/library/jj715718.aspx

error C3767: candidate function(s) not accessible Visual Studio 2010

I'm getting this error:
error C3767: 'phys1::point::get_prev': candidate function(s) not accessible
Here's my code
phys.h
using namespace System;
namespace phys1 {
typedef struct position{
int x;
int y;
} pos;
public ref class point{
public:
point(float speed, float gr);
public:
pos get_prev();
public:
pos get_next();
};
}
phys.cpp
// This is the main DLL file.
#include "phys.h"
using namespace System;
namespace phys1 {
...
static pos point::get_prev(){
pos point;
point.x=x;
point.y=y;
return point;
}
...
}
Is it problem with my struct, which i try to use in library? Can i build it in another way?
You are mixing C++ syntax and C++/CLI syntax. The "struct" is a native definition (a C++ one).
To declare 'struct' you should better use the "value struct" construction.
The "not accessible" error can also be due to the 'position' being implicitly declared as 'private'.
See more about managed type declarations here: http://www.codeproject.com/Articles/17741/C-CLI-in-Action-Declaring-CLR-types
If you're trying to pass values of type pos across an assembly boundary, it should be a public managed type. public value struct pos would be most appropriate for what you're doing.
Native types aren't visible across assembly boundaries by default, and the #pragma that makes them visible is more of a kludge than a real solution. Just make a proper .NET type with metadata.

LNK2001 unresolved external when importing functions from MFC DLL

I have created an MFC DLL and have exported the functions for example in the file SerialPort.h:
class CSerialPortApp : public CWinApp
{
public:
CSerialPortApp();
__declspec(dllexport) int SWrite(unsigned char* toSend, int len);
};
and in my MFC application I want to call the function in SerialInterface.h I have included the "SerialPort.h" from the DLL and called:
__declspec(dllimport) int SWrite(unsigned char* toSend, int len);
class SerialInterface
{
public:
};
for example.
I have added the SerialPort.lib file to my linker includes but when I try to compile I get
error LNK2001: unresolved external symbol "__declspec(dllimport) int __cdecl SWrite(unsigned char*, int)" (__imp_?SWrite##YAHPAEH#Z)
I am stuck as to the cause of this, I have tried rebuilding everything but nothing seems to help?
Thank you for any help!
You are using __declspec(dllexport) inside a class?
You either export global functions from the dll or whole class which may contain any functions. You don't have to export selected member functions from a class, I don't even know how that works.
It is a little strange that you are not properly exporting the SerialPort class from dll (as per your code) yet you can use it in your application and call its member function!? I am a little confused.
Well I found an alternative that works, I believe I was implementing it incorrectly.
I added a new class to my DLL that was not a CWinApp class:
class SerialPort
{
public:
__declspec(dllexport) SerialPort(void);
__declspec(dllexport) virtual ~SerialPort(void);
__declspec(dllexport) int SWrite(unsigned char* toSend, int len);
};
then included the header for this in my application and the lib and dll etc.
I then placed the included header file in the main CDialog header but importantly didn't need to import any of the functions:
#include "SerialPort.h"
class CPPUDlg : public CDialog
{
public:
CPPUDlg(CWnd* pParent = NULL); // standard constructor
SerialPort objSerialPort;
and then in my code I simply call
objSerialPort.SWrite(toSend, len);
I have not used dllimport to import the functions which I assumed I would need to but it now works!
Hope this helps anyone who may have a similar problem.

How to use "this" in a thread!

I am trying to call my static function using a separate thread, I have in my function something like this->listBox1->Items->Add(s);. The compiler shows that I can't use this inside a static function. I tried to make my function non-static (i.e remove static keyword) but when I did that, again the compiler shows two errors which are:
Error 2 error C3350: 'System::Threading::ThreadStart' : a delegate constructor expects 2 argument(s) c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 116
Error 1 error C2276: '&' : illegal operation on bound member function expression c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 116
Edit:
The function:
void ScanMyDir(String^ SourceDir)
{
array <String^> ^fileEntries = Directory::GetFiles(SourceDir);
for each (String^ fileName in fileEntries)
this->Form1->listBox1->Items->Add(fileName);
array<String^> ^SubDirEntries = Directory::GetDirectories(SourceDir);
for each (String^ subdir in SubDirEntries)
if ((File::GetAttributes(subdir) & FileAttributes::ReparsePoint)!= FileAttributes::ReparsePoint)
ScanMyDir(subdir);
}
Way to call it:
void button1_Click(System::Object^ sender, System::EventArgs^ e) {
Thread ^thr1 = gcnew Thread(gcnew ParameterizedThreadStart(this,&Form1::ScanMyDir));
thr1->Start("c:\\");
}
Modification on Form load:
void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
System::Windows::Forms::Control::CheckForIllegalCrossThreadCalls = false;
}
The new errors :( :
Error 5 error C3352: 'void testScan::Form1::ScanMyDir(System::String ^)' : the specified function does not match the delegate type 'void (System::Object ^)' c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 117
Error 1 error C2273: 'function-style cast' : illegal as right side of '->' operator c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 105
Error 2 error C2227: left of '->listBox1' must point to class/struct/union/generic type c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 105
Error 3 error C2227: left of '->Items' must point to class/struct/union/generic type c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 105
Error 4 error C2227: left of '->Add' must point to class/struct/union/generic type c:\users\ahmed\documents\visual studio 2010\projects\testscan\testscan\Form1.h 105
No need to make your function static. Given errors are due to the wrong syntax you are using.
Assuming your form type as FormType,
void ScanMyDir()
{
//....
}
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
Thread ^thr1 =gcnew Thread(gcnew ThreadStart(this,&FormType::ScanMyDir));
thr1->Start();
}
If you insist on making it static, like #jgauffin said pass the form as an Object parameter to ScanMyDir() and then recast it to form in the function.
static void ScanMydir(Object ^ param)
{
FormType ^ ft = static_cast<FormType^>(param);
//..
ft->listBox1->Items->Add(fileName);
//..
}
In this case you have to use ParametrizedThreadStart()
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
Thread ^thr1 =gcnew Thread(gcnew ParametrizedThreadStart(&FormType::ScanMyDir));
// it is static no need for "this"
thr1->Start(this);
}
But at least make the ScanMyDir() function private and prevent outside access.
Now probably you will have another error, saying "you can not touch GUI with different threads", then on your forms loading function write
void FormType_Load(Object ^sender, EventArgs ^ e)
{
System::Windows::Forms::Control::CheckForIllegalCrossThreadCalls = false;
//....
}
But this may be dangerous depending on your implementation, you have to guarantee the thread-safety of listbox1->items.
Also listen to what the #Yochai Timmer guy said. He is telling good things.
Ok, basic principles:
Static means that the method is NOT a member of the object. It's a member of the Class type, and is in common to all the objects of that class. So, there's no this because there's no object associated.
Read the compiler errors. Read the function definitions to pass th right parameters...
When you get this working, you'll probably have an error because you're trying to use GUI function's from a different thread. That will cause run-time errors (sometimes).
Check this: UI Thread .Invoke() causing handle leak?
Disclaimer: I haven't used managed C++, only C# and vanilla C++. Therefore this answer might be incorrect.
ThreadStart delegate can take a parameter. Pass the instance of your class to it and cast it to your class in the static thread method. It's not this, but almost the same thing.

Resources