C++/CLI I can't add a class to my collection - c++-cli

I am attempting to simply add a FilterInfo class to my FilterInfo collection. I'm having a terrible time trying to understand why the following code keeps throwing the error:
System::Collections::Generic::List::Add'
: cannot convert parameter 1 from
'Ziz::FilterInfo *' to
'Ziz::FilterInfo'
I'm only learning C++/CLI, as I'm a C# developer, and I'm sure it's something simple, but I sure could use some pointers. My stripped code is as follows:
public value class FilterInfo
{
public:
char* Address;
};
public ref class Ziz
{
private:
List<FilterInfo>^ _blockList;
public:
// Constructor
Ziz(){
_blockList = gcnew List<FilterInfo>();
}
List<FilterInfo>^ GetBlockList()
{
for each(_IPFILTERINFO ip in _packetFilter->GetBlockList())
{
// _IPFILTERINFO is the native C++ struct.
FilterInfo* f = new FilterInfo();
_blockList->Add(f);
}
return _blockList;
}

You declared _blockList as
List<FilterInfo>^ _blockList;
but you are trying to add
FilterInfo* f
to it. It cannot work since one is a pointer and the other one is a reference.
I'm not sure how "value" fits in but in
public value class FilterInfo
{
public:
char* Address;
};
You are derefore declaring an unmanaged class
to make it managed, you should use
public ref class FiterInfo
This will allow you to use FilterInfo* without having to manage memory explicitely.
Finally, char* is not so great in C++/CLI, I would recommend using System::String

_blockList->Add(*f);

You have to construct your FilterInfo with gcnew as well. You can't really mix and mash these together without marshaling.

FilterInfo is not FilterInfo*. If you want a List of pointers to FilterInfo, you need to say that List<FilterInfo*>. Since FilterInfo is a value class here though you'll likely just want to skip the new.
FilterInfo fi;
_blockList->Add(fi);

public ref class A
{
};
int main(array<System::String ^> ^args)
{
Console::WriteLine(L"Hello World");
ICollection<A^>^ oCollection = gcnew List<A^>();
oCollection->Add(gcnew A());
return 0;
}

Related

Static Object of a class in another class in aggregation relationship C++

I have two classes first class contains the object of another class as static but C++ doesnot allow me to do this and gives me some error.
source.cpp
#include"control.h"
int main()
{
Controller cnt;
cnt.tempcont();
return 0;
}
control.h
#include"recorder.h"
class Controller
{
public:
static recorder rec;
void tempcont();
};
recorder Controller::rec;
control.cpp
#include"control.h"
void Controller::tempcont()
{
rec.temprec();
}
recorder.h
#include<iostream>
using namespace std;
class recorder
{
public:
int a;
void temprec();
};
recorder.cpp
#include"recorder.h"
void recorder::temprec()
{
cout << "temp rec called";
}
I am getting the following errors and i have no idea why these errors are comming..
Error LNK1169 one or more multiply defined symbols found
Error LNK2005 "public: static class recorder Controller::rec" (?rec#Controller##2Vrecorder##A) already defined in control.obj
You define the variable Controller::rec in the header file. That means the variable will be defined in every translation unit where that header file have been included. It should only be defined in one single translation unit.
This is very easy to do: Just move the definition to a single source file.

Different function definition after compilation

I have my Keyboard class:
namespace BSGameFramework
{
namespace Input
{
static public ref class Keyboard
{
public:
static KeyboardState GetState();
};
}
}
Where KeyboardState is a ref struct.
After compilation as dll from my C# application I see the function from metadata as follow:
namespace BSGameFramework.Input
{
public class Keyboard
{
public Keyboard();
public static void GetState(ref KeyboardState value);
}
}
Keyboard class has lost its static state and the function GetState is now returning void and taking a KeyboardState as referenced parameter!
Somebody know why? Thanks in advance :D
The reason is because of the return type, ref struct KeyboardState.
In C++/CLI, the "ref" vs. "value" is the thing that determines whether a type is a reference type or a value type, not "class" vs. "struct". ref class and ref struct are both the same thing as C#'s class. value class and value struct are both the same thing as C#'s struct.
Therefore, you have a C++/CLI method declared as returning a reference type, but without the ^. This data type does exist in C++/CLI, but not in C#. The method signature you see is a workaround.
There are two possible solutions to this issue:
Change KeyboardState to a value struct. From what you said, it sounds like you intended for this to be a value type from the beginning, so this is probably the best solution.
Change the return type of the method to KeyboardState^. This will let the method show up in C# the same as it does in C++/CLI. However, if you do this, you'll want to switch all uses of KeyboardState to KeyboardState^. It's a reference type, it should be used with a ^.

Calling a function from a header in Visual C++ 2010

I'm programming in Visual C++ 2010. I've got a example.h example.cpp and Form1.h.
Basically, I've pasted bits of code. I'm not able to include Form1.h in the example.h file, not sure why. But The main question is how do I call Test (which is in form1.h) from example.cpp? What would be the syntax? Is it possible to do this?
My Form1.h
#include "example.h"
public ref class Form1 : public System::Windows::Forms::Form
{
public: void Test(void)
{
// Does something
}
}
My example.cpp
#include "example.h"
#include "Form1.h"
Test(); // would like to call Test from here.
You have two problems here:
You must call functions from inside of another function. The code you currently have in your example.cpp file is invalid, because you are trying to call the Test() function at global scope.
Make it look like this instead:
int main()
{
Test();
return 0;
}
This also solves the problem that you don't have a main function, which is the entry point to any C++ application.
More generally, I would strongly recommend using one of the project templates that comes with Visual Studio to get started (rather than copying and pasting random bits of code, like you said). That ensures that you have all of the things you need to get started, like an entry point. Once you have a solid foundation, you can start building up from there.
You might also find it useful to obtain either a book on C++/CLI or an online tutorial (such as this one: Hello C++/CLI, Part 1 and Hello C++/CLI, Part 2).
Your Test function is a member function of the Form1 class, which means that you need an object of that class in order to call it. Thus, the code should actually look like this:
int main()
{
Form1^ frm = gcnew Form1();
frm.Test();
return 0;
}
Alternatively, you could work around this by making the Test() function a static function. This would allow you to call it without having an instance of the class:
public ref class Form1 : public System::Windows::Forms::Form
{
public: static void Test(void)
{
// Does something
}
}
// ...
int main()
{
Form1::Test();
return 0;
}
However, beware that this means you cannot access any other members of the Form1 class inside of the Test() function (because there is no this pointer).
This should all be explained in whatever book/tutorial you decide to use to learn C++/CLI—search for a chapter about "Classes" or "Object-Oriented Design".

System.NullReferenceException when using gcroot

Turns out this error had nothing to do with gcroot - I connected some constructors shoddily and lost the instantiated object on the way.
For the record, all versions of the code below worked after this fix, but adding the simple Wrapper class allows you to use & and * operators on the wrapped object, which gcroot forbids. I am using the version outlined in the third code block below.
I am trying to use some measuring instruments via a .dll, but I am having problems with the implementation. Writing all the code into the main.cpp and using the object like this works fine:
#using "M3D_FP_USB.dll"
int main(){
M3D_FP_USB ^obj = gcnew M3D_FP_USB;
obj->Connect();
...
}
However, when I put it into a class and wrap it with gcroot, I get an "Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of the object" on execution.
class User{
...
public:
User();
gcroot<M3D_FP_USB^> obj;
}
User::User(){
obj = gcnew M3D_FP_USB;
obj->Connect();
...
}
I suspect that the gcroot or it being called inside the unmanaged class might prevent the instruments from accessing the M3D_FP_USB object. I tried adding a managed Wrapper class, and give a handle to the Wrapper object to the User class. That didn't solve the problem, though.
class User{
...
public:
gcroot<Wrapper^> wobj;
}
ref class Wrapper{
...
public:
M3D_FP_USB^ iobj;
...
}
Wrapper::Wrapper(){
iobj = gcnew M3D_FP_USB;
iobj->Connect();
...
}
The new code I have looks like this, but I couldn't test it with the instruments yet. I will update when I get the chance.
Wrapper::Wrapper(M3D_FP_USB^ obj){
iobj = obj;
iobj->Connect();
...
}
int main(){
M3D_FP_USB ^obj = gcnew M3D_FP_USB;
Wrapper Ex(obj);
}
Does the exception also happen if you make the class managed and just declare the handle directly? Like:
ref class User
{
public:
M3D_FP_USB^ obj;
...
};
Though I don't see why it wouldn't work the way you're doing it...

using jna with FAR PASCAL custom dll

I am using JNA to access a custom DLL which seems to be using the FAR PASCAL Calling Conventions, but the JVM crashes every time i try to access it.
Development Guide of the dll says:
BOOL FAR PASCAL GetIomemVersion(LPSTR);
And Dependency Walker tells me:
_GetIomemVersion#4
public class PebblePrinter {
public interface Iomem extends StdCallLibrary {
boolean _GetIomemVersion(String version);
}
String version;
Iomem INSTANCE;
StdCallFunctionMapper myMapper;
public PebblePrinter() {
HashMap optionMap = new HashMap();
myMapper = new StdCallFunctionMapper();
optionMap.put(Library.OPTION_FUNCTION_MAPPER, myMapper);
INSTANCE = (Iomem)Native.loadLibrary("iomem", Iomem.class,optionMap);
}
public String getIomemVersion(){
INSTANCE._GetIomemVersion(version);
return version;
}
}
With C# code it works well using
[DllImport("iomem.dll", EntryPoint = "_GetIomemVersion#4")]
public static extern bool GetIomemVersion(IntPtr version);
Can you tell me what i am doing wrong?
Thanks in advance!!!
Problem solved,
I've just used the wrong parameter ..
GetIomemVersion needs a Pointer
boolean _GetIomemVersion(Pointer version);
public String getIomemVersion(){
Memory m = new Memory(1024);
Pointer x = m.getPointer(0);
INSTANCE._GetIomemVersion(x);
return x.getString(0);
}