C++ wrapper pass pointer address to native class - visual-studio

Hello I am trying to pass a pointer address from a managed class to an unmanaged
class. So every A-Object has a reference to a B-object. But if I pass the reference in _a = new A(_managedB->_b) the compiler throws an error that no constructor matches the argument list.
So what's wrong with the code?
unmanaged code:
class A
{
private:
B &b;
public:
explicit
A(B& b);
~A();
}
managed code:
public ref class ManagedA
{
private:
ManagedB ^_managedB;
A *_a;
public:
ManagedA::ManagedA(ManagedB ^managedB ): _managedB(managedB)
{
_a = new A(_managedB->_b);
}
ManagedA::~ManagedA(ManagedB ^managedB ): _managedB(managedB)
{
delete _a;
_a = 0;
}
};

Ok I did it like this and it worked.
I don't know if the situation is interpreted right, but I am not trying to pass a Handle as a pointer. I pass a pointer that is a member of an Handle.
public ref class ManagedA
{
private:
ManagedB ^_managedB;
A *_a;
public:
ManagedA::ManagedA(ManagedB ^managedB ): _managedB(managedB)
{
_a = new A(*_managedB->_b);
}
ManagedA::~ManagedA(ManagedB ^managedB ): _managedB(managedB)
{
delete _a;
_a = 0;
}
};

Related

C++ error: using temporary as lvalue when using member variable of container in dervied class

#include<iostream>
class acc{
public:
acc() { aa = 10;}
int aa;
};
class Derv;
class Base{
public:
Base() {}
int a;
virtual acc get_acc() {};
virtual void compare(Derv *v) {}
};
class Derv : public Base {
public:
acc acc_o;
Derv() {}
virtual acc get_acc();
virtual void compare(Derv *v) {
if(v->get_acc().aa = acc_o.aa) {
std::cout<<"Values Match\n";
}
}
};
acc Derv::get_acc() {
return acc_o;
}
int main() {
Base *d1 = new Derv();
Base *v = new Derv();
Derv *v1 = dynamic_cast<Derv *>(v);
d1->compare(v1);
std::cout<<d1->get_acc().aa<<std::endl;
return 0;
}
Above code is giving compiler error when compiled using gcc. Following is the compiler error:
accessor_test.cpp: In member function ‘virtual void Derv::compare(Derv*)’:
accessor_test.cpp:25:40: error: using temporary as lvalue [-fpermissive]
if(v->get_acc().aa = acc_o.aa) {
Not able to understand what is the reason for error? Can someone help me understand the error and possible fix for the same?

Stateless Lambda and Private members

In certain cases when programming with libraries written in C involving callbacks, I like to use Lambda expressions; however, if I need to alter the state of a class member variable I can't juts pass this into a stateless(function pointer) lambda. But I can assign this to a data in a context structure. What I find strange is being able to access that member variable even if it's private in the class.
Here's an example code I wrote to demonstrate.
#include <iostream>
using std::cout;
typedef struct extradatatype{
void* data;
}extradata;
extradata e = {0};
typedef void(*callback)(extradata* e);
void cb(callback c){
c(&e);
}
class Test{
private:
int x;
public:
Test(int x){
this->x = x;
}
void setcb(){
cb([](extradata* e){
Test* self = reinterpret_cast<Test*>(e->data);
self->x = 20;
});
}
int getx(){
return x;
}
};
int main(){
Test t(10);
e.data = &t;
t.setcb();
cout << t.getx();
return 0;
}
In the Lambda expression Test* self is assigned to e->data but I can access self->x as if it were a public member instead of private. So what I'm confused about is, is the lambda expression expression being executed within the stack/context of the setcb function or is it being executed elsewhere as its own function but C++ is doing some weird trick to allow private members to be accessed. Because I assume a stateless lambda is really no different than a non member static function which has no access to private members of a class.
Since your lambda function is defined within the class Test context, it will have access to class Test private member (regardless if it's this.x or self.x where self is of type Test). It is similar to this example:
class Example {
private:
int x;
public:
int f(Example e) {
return e.x;
}
};
where, since f is a member of Example, it can access e.x because e has type Example.
If you move your lambda function definition out of the class context you'll see the expected error message:
void outside(extradata* e);
class Test{
private:
int x;
public:
void setcb(){
cb(outside);
}
};
void outside(extradata* e) {
Test* self = reinterpret_cast<Test*>(e->data);
self->x = 20; // error here!
}
test.cpp:32:11: error: 'int Test::x' is private within this context
self->x = 20;
^

Can a method of an class (in a shared_ptr) be tied to a static function in a traits class?

Historically, I've been using trait classes to hold information and apply that into a "generic" function that runs the same "algorithm." Only differed by the trait class. For example: https://onlinegdb.com/ryUo7WRmN
enum selector { SELECTOR1, SELECTOR2, SELECTOR3, };
// declaration
template < selector T> struct example_trait;
template<> struct example_trait<SELECTOR1> {
static constexpr size_t member_var = 3;
static size_t do_something() { return 0; }
};
template<> struct example_trait<SELECTOR2> {
static constexpr size_t member_var = 5;
static size_t do_something() { return 0; }
};
// pretend this is doing something useful but common
template < selector T, typename TT = example_trait<T> >
void function() {
std::cout << TT::member_var << std::endl;
std::cout << TT::do_something() << std::endl;
}
int main()
{
function<SELECTOR1>();
function<SELECTOR2>();
return 0;
}
I'm not sure how to create "generic" algorithms this when dealing with polymorphic classes.
For example: https://onlinegdb.com/S1hFLGC7V
Below I have created an inherited class hierarchy. In this example I have a base catch-all example that defaults all the parameters to something (0 in this case). And then each derived class sets overrides specific methods.
#include <iostream>
#include <memory>
#include <type_traits>
#include <assert.h>
using namespace std;
struct Base {
virtual int get_thing_one() {
return 0;
}
virtual int get_thing_two() {
return 0;
}
virtual int get_thing_three() {
return 0;
}
virtual int get_thing_four() {
return 0;
}
};
struct A : public Base {
virtual int get_thing_one() override {
return 1;
}
virtual int get_thing_three() override {
return 3;
}
};
struct B : public Base {
virtual int get_thing_one() override {
return 2;
}
virtual int get_thing_four() override{
return 4;
}
};
Here I created a simple factory, not elegant but for illustrative purposes
// example simple factory
std::shared_ptr<Base> get_class(const int input) {
switch(input)
{
case 0:
return std::shared_ptr<Base>(std::make_shared<A>());
break;
case 1:
return std::shared_ptr<Base>(std::make_shared<B>());
break;
default:
assert(false);
break;
}
}
So this is the class of interest. It is a class does "something" with the data from the classes above. The methods below are a simple addition example but imagine a more complicated algorithm that is very similar for every method.
// class that uses the shared_ptr
class setter {
private:
std::shared_ptr<Base> l_ptr;
public:
setter(const std::shared_ptr<Base>& input):l_ptr(input)
{}
int get_thing_a()
{
return l_ptr->get_thing_one() + l_ptr->get_thing_two();
}
int get_thing_b()
{
return l_ptr->get_thing_three() + l_ptr->get_thing_four();
}
};
int main()
{
constexpr int select = 0;
std::shared_ptr<Base> example = get_class(select);
setter l_setter(example);
std::cout << l_setter.get_thing_a() << std::endl;
std::cout << l_setter.get_thing_b() << std::endl;
return 0;
}
How can I make the "boilerplate" inside the setter class more generic? I can't use traits as I did in the example above because I can't tie static functions with an object. So is there a way to make the boilerplate example more common?
Somewhere along the lines of having a selector, say
enum thing_select { THINGA, THINGB, };
template < thing_select T >
struct thing_traits;
template <>
struct thing_traits<THINGA>
{
static int first_function() --> somehow tied to shared_ptr<Base> 'thing_one' method
static int second_function() --> somehow tied to shared_ptr<Base> 'thing_two' method
}
template <>
struct thing_traits<THINGB>
{
static int first_function() --> somehow tied to shared_ptr<Base> 'thing_three' method
static int second_function() --> somehow tied to shared_ptr<Base> 'thing_four' method
}
// generic function I'd like to create
template < thing_select T, typename TT = thing_traits<T> >
int perform_action(...)
{
return TT::first_function(..) + TT::second_function(..);
}
I ideally would like to modify the class above to something along the lines of
// Inside setter class further above
int get_thing_a()
{
return perform_action<THINGA>(...);
}
int get_thing_b()
{
return perform_action<THINGB>(...);
}
The answer is, maybe I can't, and I need to pass int the shared_ptr as a parameter and call the specific methods I need instead of trying to tie a shared_ptr method to a static function (in hindsight, that doesn't sound like a good idea...but I wanted to bounce my idea)
Whoever makes the actual call will need a reference of the object, one way or the other. Therefore, assuming you want perform_action to perform the actual call, you will have to pass the parameter.
Now, if you really want to store which function of Base to call as a static in thing_traits without passing a parameter, you can leverage pointer to member functions:
template <>
struct thing_traits<THINGA>
{
static constexpr int (Base::*first_function)() = &Base::get_thing_one;
...
}
template < thing_select T, typename TT = thing_traits<T>>
int perform_action(Base & b)
{
return (b.*TT::first_function)() + ...;
}
You can also play instead with returning a function object that does the call for you (and the inner function takes the parameter).
It all depends on who you need to make the call and what information/dependencies you assume you have available in each class/template.

How to disable instantiating a temporary class?

I'm working with an expression template class which should not be instantiated to avoid dangling references. But I'm temped to declare a variable with auto and 'auto' create a named instance of a temporary class.
How can I disable auto declaration of temporary class in the following code?
class Base
{
};
class Temp : public Base
{
public:
Temp() {}
Temp(int, int) {}
Temp(const Temp&) = default;
Temp(Temp&&) = default;
};
Temp testFunc(int a, int b) {
return Temp{a,b};
}
int main() {
Base a = testFunc(1,2); // this should work
auto b = testFunc(1,2); // this should fail to compile
return 0;
}
You seem to want to prevent users from using auto on a particular type. That's not possible in any version of C++. If it is legal C++ for a user to write T t = <expr>;, where T is the type of <expr>, then it will be legal for a user to write auto t = <expr>; (ignoring class data members). Just as you cannot forbid someone from passing <expr> to a template function using template argument deduction.
Anything you do to prevent auto usage will also inhibit some other usage of the type.
One option would be to make Temp's constructors private, move testFunc inside the Temp class and make it static. This way you can still instantiate Base, but auto would fail because you would be calling a private constructor:
class Base
{
};
class Temp : public Base
{
Temp() {}
Temp(int, int) {}
Temp(const Temp&) = default;
Temp(Temp&&) = default;
public:
static Temp testFunc(int a, int b)
{
return Temp{a,b};
}
};
int main() {
Base a = Temp::testFunc(1,2); // this should work
auto b = Temp::testFunc(1,2); // this should fail to compile
return 0;
}
Demo

C++/CLI marshaling .NET delegate to native delegate

I am trying to pass a delegate with managed parameters to native code to be invoked. My code below runs ok, but the string output is garbage.
Native Class
Header
#pragma once
typedef void (* SegmentCreatedDelegate)(char** arg);
public class SampleClass
{
public:
SampleClass(void);
~SampleClass(void);
void DoWork(SegmentCreatedDelegate callback);
};
Code
SampleClass::SampleClass(void)
{
}
SampleClass::~SampleClass(void)
{
}
void SampleClass::DoWork(SegmentCreatedDelegate callback)
{
for(int x = 0; x< 10; x++)
{
char* myStr2 = "newsegment!";
callback(&myStr2);
}
}
Managed Class
Header
#pragma once
public ref class SampleClassNet
{
public:
delegate void SegmentCreatedDelegateNet(System::String^ arg);
SampleClassNet(void);
void DoWork(SegmentCreatedDelegateNet^ segmentCreatedCallback);
};
Code
SampleClassNet::SampleClassNet(void)
{
}
void SampleClassNet::DoWork(SegmentCreatedDelegateNet^ segmentCreatedCallback)
{
SampleClass* nativeClass = new SampleClass();
System::IntPtr pointer = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(segmentCreatedCallback);
nativeClass->DoWork((SegmentCreatedDelegate)(void*)pointer);
System::GC::KeepAlive(segmentCreatedCallback);
}
This code runs fine with the follow c#.
var sampleClass = new SampleClassNet();
sampleClass.DoWork((Console.WriteLine));
Except I get the following output, instead of the expected 10 entries of "newsegment!".
(ÇÆX
(ÇÆX☺
(ÇÆX☻
(ÇÆX♥
(ÇÆX♦
(ÇÆX♣
(ÇÆX♠
(ÇÆX
(ÇÆX
(ÇÆX
Not exactly "newsegment!", but I am not sure why the marshaling is not working. Maybe I need I need some kind of "MarshalAs" attribute so that the System::String knows that I have 8-bit chars?
As mentioned in the comments, you should convert the char** to a String^. (Btw, why pass char**, not char*? String has a constructer taking char*, which might simplify things a lot.)
I haven't tried the following, but you might give it a try:
public ref class SampleClassNet {
private:
delegate void SegmentCreatedDelegateNative(char** str);
SegmentCreatedDelegateNet^ managedCallback;
SegmentCreatedDelegateNative^ nativeCallback;
void printString(char** string);
public:
delegate void SegmentCreatedDelegateNet(System::String^ arg);
SampleClassNet();
void DoWork(SegmentCreatedDelegateNet^ segmentCreatedCallback);
};
SampleClassNet::SampleClassNet() {
nativeCallback = printString;
}
void SampleClassNet::DoWork(SegmentCreatedDelegateNet^ segmentCreatedCallback) {
SampleClass* nativeClass = new SampleClass();
managedCallback = segmentCreatedCallback;
System::IntPtr pointer = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(nativeCallback);
nativeClass->DoWork((SegmentCreatedDelegate)(void*)pointer);
}
void SampleClassNet::printString(char** string) {
if (this->managedCallback != nullptr) {
String^ str = gcnew String(*string);
managedCallback(str);
}
}
The basic idea is to use another delegate, SegmentCreatedDelegateNative, handed to the native class, and to call the actual managed delegate from the function associated with the wrapper.

Resources