Wrapper over template classes c++/cli - c++-cli

I am trying to create a c++ cli/clr wrapper over a project based on .hpp files (that does not generate .dll or .lib). My problem is as follows:
Let's say I have:
class A
{
A();
void DoAStuff();
}
class B
{
B();
void DoBStuff();
}
class C
{
C();
void DoCStuff();
}
template <typename AorB>
class AB
{
AB();
AorB GetAB();
}
template <typename CType>
class CClass
{
CClass();
CType GetCClass();
}
And inside the wrapper project I have 2 enums and a class with a method:
public enum class AorBEnum
{
A = 0,
B = 1
};
public enum class CEnum
{
C = 0
};
void UseCode(TypeForAB ab, TypeForC c)
{
unknowntype a;
unknowntype b;
switch(ab)
{
case AorBEnum::A_TYPE:
a = AB<A>();
case AorBEnum::B_TYPE:
a = AB<B>();
}
switch(c)
{
case CEnum::C_TYPE:
b = CClass(C);
}
unknowntype vala = a.GetAB();
unknowntype valb = b.GetCClass();
}
What I am trying to do is create some objects using the parameters given to UseCode, then use methods from those objects.
Imagine I have a lot more classes and enums like these.
The question is: What can I use instead of unknowntype for it to work?

Related

JUnit5 - how to pass input collection to ParameterizedTest

I'm trying to translate a ParameterizedTest from JUnit4 to JUnit5 (sadly I'm not particularly skilled in testing).
In JUnit4 I have the following class:
#RunWith(Parameterized.class)
public class AssertionTestCase {
private final TestInput testInput;
public AssertionTestCase(TestInput testInput) {
this.testInput = testInput;
}
#Parameterized.Parameters
public static Collection<Object[]> data() {
return AssertionTestCaseDataProvider.createDataCase();
}
#Test(timeout = 15 * 60 * 1000L)
public void testDailyAssertion() {
LOG.info("Testing input {}/{}", testInput.getTestCase(), testInput.getTestName());
//assert stuffs
}
}
in the AssertionTestCaseDataProvider class I have a simple method generating a collection of Object[]:
class AssertionTestCaseDataProvider {
static Collection<Object[]> createDataCase() {
final List<TestInput> testInputs = new ArrayList<>();
//create and populate testInputs
return testInputs.stream()
.map(testInput -> new Object[]{testInput})
.collect(Collectors.toList());
}
}
I've been trying to translate it using JUnit5 and obtained this:
class AssertionTestCase {
private final TestInput testInput;
public AssertionTestCase(TestInput testInput) {
this.testInput = testInput;
}
public static Collection<Object[]> data() {
return AssertionTestCaseDataProvider.createDataCase();
}
#ParameterizedTest
#MethodSource("data")
void testDailyAssertion() {
LOG.info("Testing input {}/{}", testInput.getTestCase(), testInput.getTestName());
// assert stuffs
}
}
I did not apply any change to the AssertionTestCaseDataProvider class.
Nevertheless, I'm getting the following error:
No ParameterResolver registered for parameter [com.xxx.xx.xxx.xxx.testinput.TestInput arg0] in constructor [public `com.xxx.xxx.xxx.xxx.xxx.AssertionTestCase(com.xxx.xxx.xxx.xxx.testinput.TestInput)]. org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [com.xxx.xx.xxx.xxx.testinput.TestInput arg0] in constructor [public com.xxx.xxx.xxx.xxx.xxx.AssertionTestCase(com.xxx.xxx.xxx.xxx.testinput.TestInput)].`
I understand I'm probably not applying correctly JUnit5 when initializing the input collection for the test. Am I missing some annotations?
I've also tried to use #ArgumentSource instead of #MethodSource and implementing Argument for AssertionTestCaseDataProvider, with the same failing results.
It works in a bit another way in Junit5.
Test Method should have parameters, and provider method should return a Stream.
static Stream<Arguments> data(){
return Stream.of(
Arguments.of("a", 1),
Arguments.of("d", 2)
);
}
#ParameterizedTest
#MethodSource("data")
void testDailyAssertion(String a, int b) {
Assertions.assertAll(
() -> Assertions.assertEquals("a", a),
() -> Assertions.assertEquals(1, b)
);
}
In your case you can just return a Stream<TestInput>:
static Stream<TestInput> createDataCase() {
final List<TestInput> testInputs = new ArrayList<>();
//create and populate testInputs
return testInputs.stream();
}
and then in your testMethod:
#ParameterizedTest
#MethodSource("createDataCase")
void testDailyAssertion(TestInput testInput) {
{your assertions}
}

In C++/CLI what is the easiest way to pass internal variables to delegate?

I am trying to set a delegate that takes a local variable as a parameter. The declaration looks like this:
ref class Main
{
private:
Func<String^>^ _expensiveMethodDelegate;
public:
property Func<String^>^ ExpensiveMethodDelegate
{
Func<String^>^ get() { return this->_expensiveMethodDelegate; }
void set(Func<String^>^ value) { this->_expensiveMethodDelegate = value; }
};
void DoWork()
{
String^ result = this->_expensiveMethodDelegate();
Debug::WriteLine(result);
}
};
In C# the code will look like this:
string parameter = "value";
Main main = new Main();
main.ExpensiveMethodDelegate = () =>
{
Thread.Sleep(1000); // do expensive work
return parameter + "1";
};
main.DoWork();
What is the easiest way of achieving this goal using managed C++ (VS 2015)? Note: I read articles Workaround for not having lambdas that can capture managed variables and Lambda expressions as CLR (.NET) delegates / event handlers in Visual C++ 2010 and still cannot figure out what is the solution.
I tried code like this (using make_delegate from the second article), but it fails to compile:
String^ parameter = L"value";
Main^ main = gcnew Main();
main->ExpensiveMethodDelegate = make_delegate(
[](String^ parameter) -> String^
{
Threading::Thread::Sleep(1000); // do work
return parameter + L"1";
});
main->DoWork();
This is what I came up with:
#pragma once
#include <new>
using namespace std::tr1;
using namespace System;
namespace helper
{
private struct return_type_helper
{
private:
template<class D>
struct dependent_false { enum { value = false }; };
template <class D>
struct illegal_delegate_type
{
static_assert(dependent_false<D>::value, "Delegates with more than 2 parameters, or with parameters of tracking reference types (T%), are not supported.");
};
struct anything
{
template<class T>
operator T() const;
};
public:
template<class D>
static decltype(static_cast<D^>(nullptr)(anything())) dummy(int(*)[2]);
template<class D>
static decltype(static_cast<D^>(nullptr)(anything(), anything())) dummy(int(*)[3]);
};
template<class Func, class Aligner = char, bool Match = (alignment_of<Func>::value == alignment_of<Aligner>::value)>
struct aligner
{
static_assert(Match, "Function object has unsupported alignment");
};
template<class Func, class Aligner>
private struct aligner<Func, Aligner, true>
{
typedef Aligner type;
};
template<class F>
private ref class lambda_wrapper
{
public:
lambda_wrapper(const F& f)
{
pin_ptr<F> pf = (interior_ptr<F>)&f_storage;
new(pf) F(f);
}
~lambda_wrapper()
{
pin_ptr<F> pf = (interior_ptr<F>)&f_storage;
pf->~F();
}
template <class D>
operator D ^ ()
{
D^ d = nullptr;
return gcnew D(this, &lambda_wrapper<F>::invoke<decltype(return_type_helper::dummy<D>(0))>);
}
private:
template<class T>
[System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential, Size = sizeof(T))]
value struct embedded_storage
{
private:
typename aligner<T>::type dummy;
};
embedded_storage<F> f_storage;
template<class R, class A1>
R invoke(A1 a1)
{
pin_ptr<F> pf = (interior_ptr<F>)&f_storage;
return (*pf)(a1);
}
template<class R, class A1, class A2>
R invoke(A1 a1, A2 a2)
{
pin_ptr<F> pf = (interior_ptr<F>)&f_storage;
return (*pf)(a1, a2);
}
};
template <typename...>
ref class DelegateHelper;
template<class TParam1, class TResult>
ref class DelegateHelper<TParam1, TResult>
{
private:
Func<TParam1, TResult>^ _lambda;
TParam1 _param1;
TResult Execute()
{
return this->_lambda(this->_param1);
}
public:
template<class TLambda>
DelegateHelper(TLambda lambda, TParam1 param1)
{
this->_lambda = gcnew helper::lambda_wrapper<TLambda>(lambda);
this->_param1 = param1;
}
static operator Func<TResult> ^ (DelegateHelper<TParam1, TResult>^ value)
{
return gcnew Func<TResult>(value, &DelegateHelper<TParam1, TResult>::Execute);
}
};
template<class TParam1, class TParam2, class TResult>
ref class DelegateHelper<TParam1, TParam2, TResult>
{
private:
Func<TParam1, TParam2, TResult>^ _lambda;
TParam1 _param1;
TParam2 _param2;
TResult Execute()
{
return this->_lambda(this->_param1, this->_param2);
}
public:
template<class TLambda>
DelegateHelper(TLambda lambda, TParam1 param1, TParam2 param2)
{
this->_lambda = gcnew helper::lambda_wrapper<TLambda>(lambda);
this->_param1 = param1;
this->_param2 = param2;
}
static operator Func<TResult> ^ (DelegateHelper<TParam1, TParam2, TResult>^ value)
{
return gcnew Func<TResult>(value, &DelegateHelper<TParam1, TParam2, TResult>::Execute);
}
};
}
This is how to use it:
String^ parameter1 = L"value1";
String^ parameter2 = L"value2";
Main^ main = gcnew Main();
auto lambda1 = [](String^ parameter) -> String^
{
Threading::Thread::Sleep(1000);
return parameter;
};
main->ExpensiveMethodDelegate = gcnew helper::DelegateHelper<String^, String^>(lambda1, parameter1);
main->DoWork();
auto lambda2 = [](String^ parameter1, String^ parameter2) -> String^
{
Threading::Thread::Sleep(1000);
return parameter1 + parameter2;
};
main->ExpensiveMethodDelegate = gcnew helper::DelegateHelper<String^, String^, String^>(lambda2, parameter1, parameter2);
main->DoWork();
Not sure if it is the most elegant way, but it does the work I was looking for.

How to access private variable in C++/CLI managed class

//MyWrapper.h
#include "arithmetic.h"
#include "mathematics.h"
namespace MyWrapper {
public ref class ClassA
{
public:
ClassA();
~ClassA();
int add(int, int);
private:
MyEngine::Arithmetic *nativeClassA;
}
public ref class ClassB
{
public:
ClassB(ClassA^ arith);
~ClassB();
int pow(int, int);
private:
MyEngine::Mathematics *nativeClassB;
}
}
//MyWrapper.cpp
#include "MyWrapper.h"
My::ClassA::ClassA()
{
nativeClassA = new MyEngine::Arithmetic();
}
My::ClassA::~ClassA()
{
delete nativeClassA;
}
int My::ClassA::add(int a, int b)
{
return nativeClassA->add(a, b);
}
My::ClassB::ClassB(ClassA^ classA)
{
nativeClassB = new MyEngine::Mathematics(classA->nativeClassA); //***Error***
}
My::ClassB::~ClassB()
{
delete nativeClassB;
}
int My::ClassB::pow(int a, int b)
{
int result = nativeClassB->pow(a, b);
return result;
}
Here, Mathematics class need to init with Arithmetic class.
But nativeClassA is private variable in ClassA.
So nativeClassB = new MyEngine::Mathematics(classA->nativeClassA); , it will occurs compile error.
So I changed the nativeClassA to public.
But at that time, nativeClassA will export to c#.
I don't want to export nativeClassA variable to c#.
How can I fix it?
Thanks in advice.
Since you're writing a managed class, you can use all the access modifiers that C# has. This seems like a perfect scenario for internal. (The linked documentation is for C#, but it's the same keyword in C++/CLI.)

Why is this subclass' parent method call not polymorphic?

I've been dabbling in Dlang recently as C++ just wasn't quite sitting right with me after having used Python for so long. While dabbling, I came across what I thought would be a very simple exercise in polymorphism. I suppose how you would expect something to work and what it actually does are two entirely different things for reasons an end user probably can't comprehend. That being said, here is the source code of my "sandbox.D":
import std.stdio;
class Animal {
string voice = "--silence--";
void speak() {
writeln(this.voice);
}
}
class Dog : Animal {
string voice = "Whoof!";
}
int main() {
auto a = new Animal();
auto d = new Dog();
writeln(a.voice); // Prints "--silence--"
writeln(d.voice); // Prints "Whoof!"
a.speak(); // Prints "--silence--"
d.speak(); // Prints "--silence--" NOT "Whoof!"
return 0;
}
I guess my issue is why the "this" keyword just doesn't seem to be functioning how you would expect it to in the C++ successor language.
Methods are polymorphic, variables aren't. So instead of making the voice a variable, you want to override speak in the child.
Also, the auto return type doesn't work with polymorphism, you need to actually specify the types. (The reason is that auto return makes a function template in the compiler, which in theory could have multiple overridable slots in the function table, so it just doesn't try to put it in.)
So try this out:
import std.stdio;
class Animal {
void speak() { // changed to void instead of auto
writeln("--silence--");
}
}
class Dog : Animal {
override void speak() { // the override tells it to override the base method
writeln("woof");
}
}
int main() {
auto d = new Dog();
d.speak();
return 0;
}
If you have a lot of shared functionality and want to reuse one function with slight changes in child classes, you might make a method instead of a variable that just returns something.
Like string voice() { return "woof"; }, then it can be overridden in children.
Another way is to use template this parameter:
import std.stdio;
class Animal {
string voice;
void speak(this C)() {
writeln((cast(C)this).voice);
}
}
class Dog : Animal {
string voice = "Whoof!";
}
int main() {
auto a = new Animal();
auto d = new Dog();
a.speak(); // Prints ""
d.speak(); // Prints "Whoof!"
return 0;
}
Or when you do not need to have voice as a member:
import std.stdio;
class Animal {
static immutable voice = "";
void speak(this C)() {
writeln(C.voice);
}
}
class Dog : Animal {
static immutable voice = "Whoof!";
}
int main() {
auto a = new Animal();
auto d = new Dog();
a.speak(); // Prints ""
d.speak(); // Prints "Whoof!"
return 0;
}

How to define point cuts for a sequence of method(s)?

For example if I have 3 classes,
class A {
public void doA() {
/* do something */
}
}
class B {
public void doB() {
A a = new A();
a.doA();
}
}
class MyClass {
public static void main(String args[]) {
B b = new B();
b.doB();
}
}
Now I want to define a point cut for flow doB() -> doA(), like if doB() calls doA() grab parameters from class A and class B and do something in aspect method. Could someone help me out.
Let me slightly extend your sample code in order to make you understand what my solution does and what it cannot do:
class A {
public void doA() {}
}
class B {
public void doB() {
new A().doA();
new C().doC();
}
}
class C {
public void doC() {
new A().doA();
}
}
class MyClass {
public static void main(String args[]) {
new A().doA(); // should not be captured
new B().doB(); // should be captured
}
}
As you can see, there is a new class C now and we have three control flows now:
MyClass.main -> A.doA
MyClass.main -> B.doB -> A.doA
MyClass.main -> B.doB -> C.doC -> A.doA
You want to exclude #1 and capture #2, but what about #3? In this case a.doA is called indirectly from B.doB via C.doC. My solution also captures this indirect case. If this is fine for you or it does not happen in your code base, you can use my solution. Otherwise things would get a little more complicated and you would need to inspect the call stack. Tell me if you need to exclude #2, and I will extend my answer, but the solution will not look as simple as this one, I can promise.
Now here is the aspect:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class ControlFlowInterceptor {
#Before("execution(void A.doA()) && target(a) && cflow(execution(void B.doB()) && target(b))")
public void advice(JoinPoint thisJoinPoint, A a, B b) {
System.out.println(thisJoinPoint);
System.out.println(" " + a);
System.out.println(" " + b);
}
}
The console output looks like this:
execution(void A.doA())
A#7b19f779
B#65c66812
execution(void A.doA())
A#4df2868
B#65c66812
Please note that we have the same B object ID in both outputs, but because C.doC creates an new A object, we have two different A object IDs.