a member of managed class cannot be of a non-managed class type - c++-cli

I'm writing a program in c++/clr and i need to code lexical analyzer. And i have in it these:
std::map <std::string, int> classes = { { "keyword",0 },{ "identifier",0 },{ "digit",0 },{ "integer",0 },{ "real",0 },{ "character",0 },{ "alpha",0 } };
std::vector<std::string> ints = { "0","1","2","3","4","5","6","7","8","9" };
std::vector<std::string> keywords = { "if","else","then","begin","end" };
std::vector<std::string> identifiers = { "(",")","[","]","+","=",",","-",";" };
std::vector<std::string> alpha = { "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z" };
std::vector<std::string>::iterator iter;
so here is the problem: it marks classes,ints,keywords e.t.c as an error:
a member of managed class cannot be of a non-managed class type
how can i fix this?

I see You are using C++ /clr, so I assume You have strong reason for that.
Native types can not be members of Managed class. Reason for this is that machine have to know when to destroy/deallocate memory occupied by native code -> they are inside manage class which objects are destroyed by garbage collector.
Anyway, you can use Managed types as class members ... or pointers to native types as class members - not recommended unless You want to make translation from Manage to Native or vice-versa. Here is example:
// compile with: /clr
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <string>
using namespace System;
using namespace System::Collections::Generic;
public ref class MyClass
{
private:
//std::vector<std::string> ints; // Native C++ types can not be members of Managed class
List<String^>^ ints; // Managed types can be class members
std::vector<std::string>* native_ints; // However You can have pointer to native type as class member
public:
MyClass()
{ // Initialize lists with some values
ints = gcnew List<String^>(gcnew array<System::String^>{ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }); // Managed initialization
native_ints = new std::vector<std::string>{ "a", "b", "c" }; // Native initialization
}
~MyClass()
{
delete native_ints; // Native (not Managed) memory allocation have to be deleted
}
void Print()
{
Console::WriteLine("Managed List: {0}", String::Join(", ", ints->ToArray()));
std::cout << "Native vector: " << (*native_ints)[0] << ", " << (*native_ints)[1] << ", " << (*native_ints)[2];
}
};
int main(array<System::String ^> ^args)
{
MyClass^ mc = gcnew MyClass();
mc->Print();
return 0;
}
And console output is:
Managed List: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Native vector: a, b, c
Types equivalents:
std::vector -> List<T>
std::map -> SortedDictionary<Tkey, Tvalue>
std::string -> String
And do not forget about ^ for managed types

Related

How to make variable in companion object protected

I want to make a variable in companion object protected. I think when I make the variable protected, it would be accessible only from another class which inherit the variable's class, not from other classes or functions. But It doesn't work.
Here's my code
open class Population{
companion object{
#JvmStatic // Though I added it because of recommendation of IntelliJ, It still doesn't work.
protected var population_quantity: Int = 0
}
}
class Marin : Population(){
init{
population_quantity += 1 // I want to make it possible
}
}
class Checker : Population() {
fun printPopulationQuantity()
{
println(population_quantity) // I also want to make it possible
}
}
fun main(){
var m1 = Marin()
var checker = Checker()
// But I want to make codes below here impossible
// Population.population_quantity += 1
// println(Population.population_quantity)
}
Below is what I want to make which is made via C++. I hope below would clarify what I'm saying.
#include <iostream>
class Population
{
protected:
static int population_quantity;
};
int Population::population_quantity = 0;
class Marin : Population
{
public:
Marin()
{
std::cout << "Marin is generated" << std::endl;
population_quantity += 1;
}
~Marin()
{
std::cout << "Marin is dead" << std::endl;
population_quantity -= 1;
}
};
class Checker : Population
{
public:
void printPopulationQuantity()
{
std::cout << population_quantity << std::endl;
}
};
int main()
{
Checker checker;
checker.printPopulationQuantity();
Marin *m1 = new Marin();
checker.printPopulationQuantity();
// std::cout << "population : " << Population::population_quantity << std::endl;
// Can't access population_quantity from main which doesn't inherite Population
// because Population::population_qantity is protected.
// But it is possible to access Population:population_quantity from Marin which inherits Population.
delete m1;
checker.printPopulationQuantity();
return 0;
}
When you help me solve this problem, I'm sure that I would feel sincere thankful from bottom of my heart.
That is probably because in class Checker : Population you have a void function which is in public.
Try changing it to this:
class Checker : Population
{
protected:
void printPopulationQuantity()
{
std::cout << population_quantity << std::endl;
}
};

Initialize C++/CLI array of structures

I wish to partially initialize an array of structures like in a C++ POD type. The String^ would normally be a char* but managed C++ doesn't allow that.
#include "stdafx.h"
using namespace System;
ref struct Field
{
String^ name;
int fences;
int length;
};
int main(array<System::String ^> ^args)
{
array<Field^>^ farm =
{
{ "eenie", 10 },
{ "meenie", 20 },
{ "miny", 4 }
};
for each (Field^ field in farm)
{
field->length = field->fences * 22;
}
return 0;
}
This results in
1>arrayinit.cpp(18): error C2440: 'initializing' : cannot convert from 'const char [6]' to 'Field ^'
1> Reason: cannot convert from 'const char *' to 'Field ^'
1> No user-defined-conversion operator available, or
1> Cannot convert an unmanaged type to a managed type
So I tried
#include "stdafx.h"
using namespace System;
ref struct Field
{
String^ name;
int fences;
int length;
};
int main(array<System::String ^> ^args)
{
array<Field^>^ farm =
{
{ String("eenie"), 10 },
{ String("meenie"), 20 },
{ String("miny"), 4 }
};
for each (Field^ field in farm)
{
field->length = field->fences * 22;
}
return 0;
}
Now I get
1>arrayinit.cpp(18): error C2440: 'initializing' : cannot convert from 'System::String' to 'Field ^'
1> No user-defined-conversion operator available, or
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>arrayinit.cpp(18): error C2078: too many initializers
Almost every example I've looked at only tells how to initialize an array of strings or integers. I haven't found out a way of initializing an array of structures containing strings.
Is there a simple way of doing this or do I have to create a special constructor and gcnew every element?
I found that I can gcnew every element with a special constructor. Is there a simpler way of doing this similar to a POD initialization?
#include "stdafx.h"
using namespace System;
ref struct Field
{
String^ name;
int fences;
int length;
Field(String^ x, int in_fences)
{
name = x;
fences = in_fences;
}
};
int main(array<System::String ^> ^args)
{
array<Field^>^ farm =
{
gcnew Field("eenie", 10 ),
gcnew Field("meenie", 20 ),
gcnew Field("miny", 4 )
};
for each (Field^ field in farm)
{
field->length = field->fences * 22;
}
return 0;
}
Alternatively, if Field is changed to a value instead of a reference,
#include "stdafx.h"
using namespace System;
value struct Field
{
String^ name;
int fences;
int length;
Field(String^ x, int in_fences)
{
name = x;
fences = in_fences;
}
void Init()
{
length = fences * 22;
}
};
int main(array<System::String ^> ^args)
{
array<Field>^ farm =
{
Field("eenie", 10 ),
Field("meenie", 20 ),
Field("miny", 4 )
};
for each (Field% field in farm)
{
field.Init();
}
return 0;
}
This is slightly better than gcnewing every field.

create my own resource types (tf.resource)

My current code:
// For Eigen::ThreadPoolDevice.
#define EIGEN_USE_THREADS 1
#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/shape_inference.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/resource_mgr.h"
#include "tensorflow/core/framework/resource_op_kernel.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/platform/macros.h"
#include "tensorflow/core/platform/mutex.h"
#include "tensorflow/core/platform/types.h"
using namespace tensorflow;
REGISTER_OP("ArrayContainerCreate")
.Attr("T: type")
.Attr("container: string = ''")
.Attr("shared_name: string = ''")
.Output("resource: resource")
.SetIsStateful()
.SetShapeFn(shape_inference::ScalarShape)
.Doc(R"doc(Array container, random index access)doc");
REGISTER_OP("ArrayContainerGetSize")
.Input("handle: resource")
.Output("out: int32")
.SetShapeFn(shape_inference::ScalarShape)
;
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/resource_mgr.h
struct ArrayContainer : public ResourceBase {
ArrayContainer(const DataType& dtype) : dtype_(dtype) {}
string DebugString() override { return "ArrayContainer"; }
int64 MemoryUsed() const override { return 0; };
mutex mu_;
const DataType dtype_;
int32 get_size() {
mutex_lock l(mu_);
return (int32) 42;
}
};
// https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/resource_op_kernel.h
class ArrayContainerCreateOp : public ResourceOpKernel<ArrayContainer> {
public:
explicit ArrayContainerCreateOp(OpKernelConstruction* context) : ResourceOpKernel(context) {
OP_REQUIRES_OK(context, context->GetAttr("T", &dtype_));
}
private:
virtual bool IsCancellable() const { return false; }
virtual void Cancel() {}
Status CreateResource(ArrayContainer** ret) override EXCLUSIVE_LOCKS_REQUIRED(mu_) {
*ret = new ArrayContainer(dtype_);
if(*ret == nullptr)
return errors::ResourceExhausted("Failed to allocate");
return Status::OK();
}
Status VerifyResource(ArrayContainer* ar) override {
if(ar->dtype_ != dtype_)
return errors::InvalidArgument("Data type mismatch: expected ", DataTypeString(dtype_),
" but got ", DataTypeString(ar->dtype_), ".");
return Status::OK();
}
DataType dtype_;
};
REGISTER_KERNEL_BUILDER(Name("ArrayContainerCreate").Device(DEVICE_CPU), ArrayContainerCreateOp);
class ArrayContainerGetSizeOp : public OpKernel {
public:
using OpKernel::OpKernel;
void Compute(OpKernelContext* context) override {
ArrayContainer* ar;
OP_REQUIRES_OK(context, GetResourceFromContext(context, "handle", &ar));
core::ScopedUnref unref(ar);
int32 size = ar->get_size();
Tensor* tensor_size = nullptr;
OP_REQUIRES_OK(context, context->allocate_output(0, TensorShape({}), &tensor_size));
tensor_size->flat<int32>().setConstant(size);
}
};
REGISTER_KERNEL_BUILDER(Name("ArrayContainerGetSize").Device(DEVICE_CPU), ArrayContainerGetSizeOp);
I compile that. Note that I first got some undefined symbol: _ZN6google8protobuf8internal26fixed_address_empty_stringE error but I resolved that by adding these additional compiler flags:
from google.protobuf.pyext import _message as msg
lib = msg.__file__
extra_compiler_flags = [
"-Xlinker", "-rpath", "-Xlinker", os.path.dirname(lib),
"-L", os.path.dirname(lib), "-l", ":" + os.path.basename(lib)]
I read about that here.
Then I load that as a module via tf.load_op_library.
Then, I have this Python code:
handle = mod.array_container_create(T=tf.int32)
size = mod.array_container_get_size(handle=handle)
When I try to evaluate size, I get the error:
InvalidArgumentError (see above for traceback): Trying to access resource located in device 14ArrayContainer from device /job:localhost/replica:0/task:0/cpu:0
[[Node: ArrayContainerGetSize = ArrayContainerGetSize[_device="/job:localhost/replica:0/task:0/cpu:0"](array_container)]]
The device name (14ArrayContainer) somehow seem to be messed up. Why is that? What is the problem with the code?
For some more testing, I added this additional code in the ArrayContainerCreateOp:
ResourceHandle rhandle = MakeResourceHandle<ArrayContainer>(context, cinfo_.container(), cinfo_.name());
printf("created. device: %s\n", rhandle.device().c_str());
printf("container: %s\n", rhandle.container().c_str());
printf("name: %s\n", rhandle.name().c_str());
printf("actual device: %s\n", context->device()->attributes().name().c_str());
printf("actual name: %s\n", cinfo_.name().c_str());
This gives me the output:
created. device: 14ArrayContainer
container: 14ArrayContainer
name: 14ArrayContainer
actual device: /job:localhost/replica:0/task:0/cpu:0
actual name: _2_array_container
So clearly, there is some of the problem.
This looks like something is messed up with the protobuf? Maybe I am linking the wrong lib? But I have not found which lib to link instead.
(I also posted an issue about this here.)
That is upstream bug 10950, which should be fixed in TensorFlow 1.2.2.

SimCardInfo issue on Blackberry10

I'd like to display/get a read on IMSI (tested it on Dev Alpha B). The issue is that I could get a read on others property of SimCardInfo such as Mobile Network Code, Mobile Country Code, Serial Number but IMSI (subscriberIdentifier).
Here is the code
main.cpp
#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>
#include <bb/device/HardwareInfo>
#include <bb/device/SimCardInfo>
#include <QLocale>
#include <QTranslator>
#include <Qt/qdeclarativedebug.h>
using namespace bb::cascades;
using namespace bb::device;
Q_DECL_EXPORT int main(int argc, char **argv)
{
qmlRegisterUncreatableType<bb::device::HardwareInfo>("bb.device", 1, 0, "HardwareInfo", "");
qmlRegisterUncreatableType<bb::device::SimCardInfo>("bb.device", 1, 0, "SimCardInfo", "");
// this is where the server is started etc
Application app(argc, argv);
// localization support
QTranslator translator;
QString locale_string = QLocale().name();
QString filename = QString( "hwinfo_%1" ).arg( locale_string );
if (translator.load(filename, "app/native/qm")) {
app.installTranslator( &translator );
}
//create object
HardwareInfo hwInfo;
SimCardInfo simcardInfo;
QmlDocument *qml = QmlDocument::create("asset:///main.qml");
qml->setContextProperty("_hardware", &hwInfo);
qml->setContextProperty("_simcardinfo", &simcardInfo);
// create root object for the UI
AbstractPane *root = qml->createRootObject<AbstractPane>();
// set created root object as a scene
Application::instance()->setScene(root);
// we complete the transaction started in the app constructor and start the client event loop here
return Application::exec();
// when loop is exited the Application deletes the scene which deletes all its children (per qt rules for children)
}
main.qml file
import bb.cascades 1.0
import bb.device 1.0
Page
{
Container
{
leftPadding: 20
topPadding: 20
Container
{
topMargin: 10
layout: StackLayout
{
orientation: LayoutOrientation.LeftToRight
}
Button
{
text: "retrieve"
onClicked:
{
lbl0.text = "Model name: " + _hardware.modelName
lbl1.text = "IMEI: " + _hardware.imei
lbl2.text = "IMSI: " + _simcardinfo.subscriberIdentifier
lbl3.text = "SN: " + _simcardinfo.serialNumber
lbl4.text = "Mobile Network Code: " + _simcardinfo.mobileNetworkCode
lbl5.text = "Mobile Country Code: " + _simcardinfo.mobileCountryCode
}
}
}
Container
{
layout: StackLayout {
}
Label
{
id:lbl0
}
Label
{
id:lbl1
}
Label
{
id:lbl2
}
Label
{
id:lbl3
}
Label
{
id:lbl4
}
Label
{
id:lbl5
}
}
}
}
Any help is much appreciated.
reference
http://developer.blackberry.com/cascades/reference/bb_device_simcardinfo.html
You're declaring hwInfo and simCardInfo as stack variables, that means that after the constructor ends both variables no longer exist, so when the QML runtime tries to access the properties you assigned to them it just can't.
To make it work you need to declare those variables as heap variables so they can outlive their scope.
HardwareInfo* hwInfo = new HardwareInfo();
SimCardInfo* simcardInfo = new SimCardInfo();
qml->setContextProperty("_hardware", hwInfo);
qml->setContextProperty("_simcardinfo", simcardInfo);

Multiple dispatch and multi-methods

What are they, what's the different between them?
Many sources, like Wikipedia, claim they're the same thing, but others explicitly say the opposite, like sbi in this question:
First: "Visitor Pattern is a way to simulate Double Dispatching in C++." This is, erm, not fully right. Actually, double dispatch is one form of multiple dispatch, which is a way to simulate (the missing) multi-methods in C++.
They are the same.
When you call a virtual method in C++, the actual method to run is based on the runtime type of the object them method is invoked on. This is called "single dispatch" because it depends on the type of a single argument (in this case, the implicit 'this' argument). So, for example, the following:
class Base {
public:
virtual int Foo() { return 3; }
}
class Derived : public Base {
public:
virtual int Foo() { return 123; }
}
int main(int argc, char *argv[]) {
Base* base = new Derived;
cout << "The result is " << base->Foo();
delete base;
return 0;
}
When run, the above program prints 123, not 3. So far so good.
Multiple-dispatch is the ability of a language or runtime to dispatch on both the type of the 'this' pointer and the type of the arguments to the method. Consider (sticking with C++ syntax for the moment):
class Derived;
class Base {
public:
virtual int Foo(Base *b) { cout << "Called Base::Foo with a Base*"; }
virtual int Foo(Derived *d) { cout << "Called Base::Foo with a Derived*"; }
}
class Derived : public Base {
public:
virtual int Foo(Base *b) { cout << "Called Derived::Foo with a Base*"; }
virtual int Foo(Derived *d) { cout << "Called Derived::Foo with a Derived*"; }
}
int main(int argc, char *argv[]) {
Base* base = new Derived;
Base* arg = new Derived;
base->Foo(arg);
delete base;
delete arg;
return 0;
}
If C++ had multiple-dispatch, the program would print out "Called Derived::Foo with a Dervied*". (Sadly, C++ does not have multiple-dispatch, and so the program prints out "Called Derived::Foo with a Base*".)
Double-dispatch is a special case of multiple-dispatch, often easier to emulate, but not terribly common as a language feature. Most languages do either single-dispatch or multiple-dispatch.