Consider the following code that can be compiled wither with or without /clr.... When compiled as a normal program (using Visual Studio 209 or 2017 or 2022) then there are no problems... but as soon as compiled and debugged with /clr problems start [note these "problems" are 100% related to the debugger, not problems with the code....
It appears that only the managed debugger is used with the watch and immediate windows, and capabilities associated with native are disabled....
class Sample
{
public:
int Foo();
static void Bar();
};
//public ref class SampleEmitter
//{
//public:
// static void Boing() { int x = 1; }
// static System::String^ Emit(Sample s)
// {
// s.Foo();
// return s.Foo().ToString();
// }
//};
int Sample::Foo()
{
return 42;
}
void Sample::Bar() { int x = 1; }
int main()
{
Sample s;
std::cout << "Hello World!\n";
}
When compiled, a breakpoint can be set on the cout.... and s.Foo() can be added to wthe watch window... It works :)
Now add /clr... and BOOM, it no longer works... However if one uncommts the SampleEmitter, that CAN be wattched....
So how to watch (evaluate) native code when compiled /clr
Related
In Arduino IDE I can create variables with custom types, but cannot return custom type from function:
This compiles
struct Timer
{
Timer()
{
}
};
Timer t;
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
int main()
{
return 0;
}
This creates Timer does not name a type error:
struct Timer
{
Timer()
{
}
};
Timer get_timer()
{
return Timer();
}
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
int main()
{
return 0;
}
Both compile in Orwell Dev-Cpp
I use MEGA-2560
You can read here about the build process of the Arduino IDE.
Before it can be compiled, your sketch needs to be transformed into a valid C++ file.
Part of this transformation is to create function defitions for all your function declarations.
These definitions are put in the top of the file, before your definition of Time. Therefore at the point of declaration of get_timer, the type Time is not declared yet.
One way to overcome this is to put all your type definitions in a separate .h file and include it into your sketch.
This C++ code compiles successfully with VS 2012 but crashes at runtime:
#include <iostream>
#include <functional>
void f()
{
std::cout << "f called" << std::endl;
}
int main()
{
auto get_f= []()
{
bool b = true;
return b ? f : f;
};
std::function<void()> filter(get_f()); // crash here!!!
return 0;
}
If we change get_f to this:
auto get_f= []()
{
return f;
};
then program runs without crashes.
Is it a problem with this code or compiler/std library bug?
I have not tested with newer versions of Visual Studio.
It looks to me like a problem with the standard library (or possibly compiler).
With VS 2013, it compiles and runs without a problem. If we add code to invoke the filter that runs as well:
#include <iostream>
#include <functional>
void f()
{
std::cout << "f called" << std::endl;
}
int main()
{
auto get_f= []()
{
bool b = true;
return b ? f : f;
};
std::function<void()> filter(get_f()); // crash here!!!
filter();
return 0;
}
Output: f called
Ok so I am trying to create a runtime DLL for another application that can be called using GetProcAddress.
So I have built the DLL in VS2012 C++ Express (Header and source below) and it returns NULL even when dll is in same folder as exe. So this lead me to believe there was an issue with the dllmain function. So I began looking through MSDN and found the following link
http://msdn.microsoft.com/en-us/library/vstudio/988ye33t.aspx
It states that it is already taken care for me when I create dll template which I did following this MSDN link.
http://msdn.microsoft.com/en-us/library/ms235636%28v=vs.80%29.aspx
So I decided to try build the DLL in release mode (thinking something about this might be the issue) but I get a linker error saying entry point must be define. It builds fine in debug mode but not in release mode. I assume I am missing something simple here.
Error 1 error LNK1561: entry point must be defined C:\Users\ProRip\Documents\Visual Studio 2012\Projects\PhantomAdapter\AdapterDLL\LINK AdapterDLL
Header
#ifdef PHANTOMADAPTER_EXPORTS
#define PHANTOMADAPTER_API __declspec(dllexport)
#else
#define PHANTOMADAPTER_API __declspec(dllexport)
#endif
#using <mscorlib.dll>
#using <system.dll>
using namespace System;
using namespace System::IO::Ports;
using namespace System::Threading;
namespace PhantomAdapter
{
class PhantomAdapter
{
public:
static PHANTOMADAPTER_API int open();
static PHANTOMADAPTER_API int close();
//static PHANTOMADAPTER_API double init(bool );
//static PHANTOMADAPTER_API int noDevices();
static PHANTOMADAPTER_API int angle(double& angle);
static PHANTOMADAPTER_API int torque(double torque);
static PHANTOMADAPTER_API int ready();
};
public ref class SerialPort
{
private:
static System::IO::Ports::SerialPort^ p1;
public:
static int openPort();
static void closePort();
static int read();
static void send(Byte data);
static int check();
};
}
Source
#include "stdafx.h"
#include "stdafx.h"
#include "PhantomAdapter.h"
#include <stdexcept>
using namespace std;
namespace PhantomAdapter
{
int PhantomAdapter::open()
{
int flag=0;
flag=SerialPort::openPort();
return flag;
}
int PhantomAdapter::close()
{
SerialPort::closePort();
return 1;
}
int PhantomAdapter::angle(double& angle)
{
SerialPort::send(0x82);
angle = (SerialPort::read() * 255) + (SerialPort::read());
angle = angle*(6.2832/512);
return 1;
}
int PhantomAdapter::torque(double torque)
{
return 1;
}
int PhantomAdapter::ready()
{
return SerialPort::check();
}
int SerialPort::openPort()
{
bool check=0;
p1 = gcnew System::IO::Ports::SerialPort();
p1->BaudRate = 57600;
p1->PortName = "COM3";
if(p1->IsOpen)
return 0;
else {
p1->Open();
return 1;
}
}
int SerialPort::check()
{
array<String^>^ serialPorts = nullptr;
int flag=0;
serialPorts = p1->GetPortNames();
for each(String^ port in serialPorts)
{
if(port=="COM3")
flag=1;
}
return flag;
}
void SerialPort::closePort()
{
p1->Close();
}
void SerialPort::send(Byte data)
{
array<unsigned char>^ buffer = gcnew array<Byte>(1);
buffer[0] = (char)data;
p1->Write(buffer,0,1);
}
int SerialPort::read()
{
return p1->ReadByte();
}
}
In your VS project, can you check the settings:
1. Configuration Properties > General > Configuration Type? Is this set to .dll in case of Release mode?
2. Configuration Properties > Linker > System > SubSystem? Is this the same between the 2 modes?
You cannot call a .NET method (and C++/CLI methods are .NET methods) from native code via LoadLibrary/GetProcAddress. .NET methods and classes are not exported that way. You will always get a NULL pointer.
What you can do:
Write a COM component in .NET to reference in plain C++
Export normal, plain C++ methods that call .NET code only internally
Import a managed dll into a managed (the same C++/CLI or C# or any other .NET language) executable by using the Assembly class and it's methods.
In Eclipse I can override the toString() method of an Object to pretty print it. This is especially useful because during a debug sessions as I can click on a variable and see the object in a human readable form.
Is there any kind of equivalent for C++ during a gdb session. I'm also open to any IDEs that can emulate this behavior.
In gdb, print command prints the contents of the variable. If you are using any IDE for C++, eg. Netbeans, Eclipse, VC++ then pointing on the variable shows the content.
EDIT: See if the below code is what you are looking for.
#include <string>
using std::string;
#define magic_string(a) #a
template<typename T>
class Object_C
{
private:
virtual string toString_Impl()
{
return magic_string(T);
}
public:
Object_C(void)
{
}
virtual ~Object_C(void)
{
}
string toString()
{
return toString_Impl();
}
};
class Base_C :
public Object_C<Base_C>
{
private:
string toString_Impl()
{
char str[80] = "";
sprintf_s(str, 79, "Base.x:%d\n", x_);
return string(str);
}
private:
int x_;
public:
Base_C(int x = 0) : x_(x) { }
~Base_C(void);
};
void ToStringDemo()
{
Base_C base;
cout << base.toString() << endl;
}
using visual Studio C++ instead?
[DebuggerDisplay("Count = {count}")]
class MyHashtable
{
public int count = 4;
}
https://learn.microsoft.com/en-us/dotnet/framework/debug-trace-profile/enhancing-debugging-with-the-debugger-display-attributes
class test
{
private:
class privateStruct
{
public:
int m;
privateStruct(int p){m=p;}
};
};
void ff()
{
test::privateStruct ps(4);
throw ps; //Does not work..
}
void main()
{
try
{
ff();
}
catch(...)
{
}
}
But the Following Code Works Why
class test
{
private:
class privateStruct
{
public:
int m;
privateStruct(int p){m=p;}
};
};
void ff()
{
throw test::privateStruct(4); //Work why
}
void main()
{
try
{
ff();
}
catch(...)
{
}
}
NOTE : I am using VC++ 6.
I need answer why the above code works.
Thanks in Advance :)
This is an old/known bug with Visual Studio 6.0. It ignores access specifiers when constructing temporaries. No fix is available.
Raising the warning level to 3 or higher (/W3) will cause the offending code to give a warning.
The code in your second example works because Visual C++ 6 is notorious for its horrible standards compliance.
It works by accident.
Even the second code snippet won't compile. privateStruct cannot be accessed in the function ff().