I'm getting this error:
error C3767: 'phys1::point::get_prev': candidate function(s) not accessible
Here's my code
phys.h
using namespace System;
namespace phys1 {
typedef struct position{
int x;
int y;
} pos;
public ref class point{
public:
point(float speed, float gr);
public:
pos get_prev();
public:
pos get_next();
};
}
phys.cpp
// This is the main DLL file.
#include "phys.h"
using namespace System;
namespace phys1 {
...
static pos point::get_prev(){
pos point;
point.x=x;
point.y=y;
return point;
}
...
}
Is it problem with my struct, which i try to use in library? Can i build it in another way?
You are mixing C++ syntax and C++/CLI syntax. The "struct" is a native definition (a C++ one).
To declare 'struct' you should better use the "value struct" construction.
The "not accessible" error can also be due to the 'position' being implicitly declared as 'private'.
See more about managed type declarations here: http://www.codeproject.com/Articles/17741/C-CLI-in-Action-Declaring-CLR-types
If you're trying to pass values of type pos across an assembly boundary, it should be a public managed type. public value struct pos would be most appropriate for what you're doing.
Native types aren't visible across assembly boundaries by default, and the #pragma that makes them visible is more of a kludge than a real solution. Just make a proper .NET type with metadata.
Related
Is there a built-in way to allow a managed ref-class to implement and expose a COM inerface that is safely callable from native code?
Looking at the C# side, this is easily done by decorating the target interface with the proper COM-interop attributes, for example:
Native Interface
interface ISampleGrabberCB: public IUnknown
{
virtual STDMETHODIMP SampleCB( double SampleTime, IMediaSample *pSample ) = 0;
virtual STDMETHODIMP BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen ) = 0;
};
static const IID IID_ISampleGrabberCB = { 0x0579154A, 0x2B53, 0x4994,
{ 0xB0, 0xD0, 0xE7, 0x73, 0x14, 0x8E, 0xFF, 0x85 } };
Managed Equivalent Interface
[Guid("0579154A-2B53-4994-B0D0-E773148EFF85")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[SuppressUnmanagedCodeSecurity]
public interface ISampleGrabberCB {
int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen);
int SampleCB(double SampleTime, IMediaSample pSample);
}
Once this declaration is done, through the magic of P-Invoke you can do something like this:
public class FooClass : ISampleGrabberCB {
int ISampleGrabberCB.BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen) {
Console.WriteLine("BufferCB called");
}
int ISampleGrabberCB.SampleCB(double SampleTime, IMediaSample pSample) {
Console.WriteLine("SampleCB called");
}
public void SomeMethod(IBaseFilter aDirectShowFilter) {
ISampleGrabber sampleGrabber = (ISampleGrabber)aDirectShowFilter;
// By the magic of PInvoke, this is possible and works!
// ISampleGrabber->SetCallback() is expecting an ISampleGrabberCB* COM interface
// After the following line, native code is able to callback safely
// into our managed code
sampleGrabber.SetCallback(this, 0);
}
}
Is there a way to mimic this behavior on C++/CLI?
Evidently, the Interop plumbing to make this possible exists as it is used by C#. Furthermore, the compiler could generate the necessary managed interface from inspecting the available native interfaces (I still think we would need to provide the relevant Guids, as this is not an attribute within the native interface)
I just got curious about this topic and played around and I found out some minor differences:
I have IVI-COM class library on my PC, and always wanted to try to interface some of them, although the IVI also has .Net interfaces so it does not make too much sense...
I started with C#, where we get good IntelliSense support. I have added the necessary references and added a class to my project. With the object browser we can select an interface.
public class MyDmm : IIviDmmMultiPoint
{
}
After that just use IntelliSense (Ctrl-.) to add the ‘using’ statement and let them make the necessary properties and methods for us.
using Ivi.Dmm.Interop;
///...
public int Count
{
get
{
throw new NotImplementedException();
}
///...
So now we need the C++-CLI dialect :) Which is as follows:
using namespace IviDmmLib;
///...
public ref class Dmm : IIviDmmMultiPoint
{
Note that the name used by the using statement is different, we can obtain this by selecting the reference at the Solution Explorer and check the name shown at the ‘Properties’ below.
I did not fully complete the experiment but I saw that the COM library was x64 bit, so we may compile the project for the same.
Further interesting readings:
Windows Runtime C++ Template Library
Please, give me feedback if you find some more differences, so we can put them here too.
I have written a header file with one basic data structure.
ProdList.h
#ifndef LISTOFITEMS_H
#define LISTOFITEMS_H
struct ListOfItems
{
public:
std::string fdcustid;
std::string fdstkid;
std::string fdordisquantity;
std::string fdordsstatus; // <> 'H'
std::string fdordhtype; // <> 'A'
};
#endif /* GRANDFATHER_H */
now that I have a data structure I include it in the class definition and use the data structure "ListOfItems" in the class "ProdContainer".
ProdContainer.h
#include "ProdList.h"
class ProdContainer
{
public:
ProdContainer(void);
~ProdContainer(void);
static void SetNumberOfElements(int Elements);
std::vector<ListOfItems> Items;
}
now when i write the following in Main.
int _tmain(int argc, _TCHAR* argv[])
{
ProdContainer myobject;
myobject.Items.resize(12);
printf("The size of Items is %i \n", myobject.Items.size());
return 0;
}
All goes as expected and I get the following output.
The size of Items is 12
Which is all fine and good. However, I want to encapsulate the data within the class and only allow access through class functions.
The problem arises when I add the following code to "SetNumberOfElements" implementation.
void ProdContainer::SetNumberOfElements(int Elements)
{
Items.resize(Elements);
}
When I try to compile this "error C2228 left of '.resize' must have class/struct/union" appears and I am at a loss at what to do next.
I have searched high and low and cant seem to find any posts matching this particular problem, it's probably a schoolboy error. I've checked the MSDN site on error C2228 and as far as I can see Items is a substantiated variable of struct type ListOfItems, so I can't see why this error is appearing.
Is there a method for accessing a vector of a struct or some other aspect that I just can't see.
Please help, I am just about ready to explode.
You can only access static data from static functions. So change this
static void SetNumberOfElements(int Elements);
To this
void SetNumberOfElements(int Elements);
You cannot access non-static class members from the static function.
What you can do is to "switch" from static to non-static.
static void SetNumberOfElements( void * lParam, int Elements)
{
((ProdContainer*)lParam)->Items.resize( Elements );
}
Use it like this inside your class:
SetNumberOfELements( this, 10 );
Making the shift from C++ to C++/CX I stumbled upon that ref classes can't have native members in they're public or protected members, due to possible errors with java and stuff. Instead we now have to use properties, which I can make but only to hold 1 value...
The idea was to make a property that would store 4 floats in an array or vector and later pass the values to a XMVECTOR. The relevant code I have in the class header file until now is:
public:
property std::vector<float> num{
void set(std::vector<float> e){
NUM = e;
};
std::vector<float> get(){
return NUM;
};
};
private:
std::vector<float> NUM;
Later in the .cpp file I do:
std::vector<float> g;
g.pushback(3);
num = g;
I also make it a string to pass to a TextBox(but that's not important). In the end I just get many similar errors... The 2 errors are:
error C3986: 'set': signature of public member contains native type 'std::vector<_Ty>'
error C3986: 'set': signature of public member contains native type 'std::allocator<_Ty>'
The only thing I imagine is that I can't use strings or vectors. I know Platform::Strings exist but what about vectors??
Standard C++ types cannot be projected across the WinRT ABI, which is the communication layer shared by all WinRT language projections (C#/VB/JS). As Jagannath mentions, there is a collection interface (Windows::Foundation::Collections::IVector<T>). There is also a dictionary type (IMap<K,V>) and various iterators and support types. These are understood by all languages, but are just interfaces. Each language projection is responsible for authoring runtime classes that implement these interfaces. For C++/Cx, these ref classes are found in the header <collection.h> and are in the namespace Platform::Collections. Platform::Collections::Vector<T> and Platform::Collections::Map<K,V> are the basic types you can use as backing stores. Additionally, Vector<T> can be move-constructed from std::vector<T>.
However, you can't make a public property of type Platform::Collections::Vector<T> either, as this is still a C++ type. What you do instead is create a public property of type Windows::Foundation::Collection::IVector<T> which is backed by a private member variable of type Platform::Collections::Vector<T>.
Essentially:
public:
property Windows::Foundation::Collections::IVector<float>^ num{
Windows::Foundation::Collections::IVector<float>^ get(){
return NUM;
}
}
private:
Platform::Collections::Vector<float>^ NUM;
I have avoided mentioning the property setter, because that gets tricky (your private type would need to also be an IVector and it will only be a Platform::Collections::Vector if it came from C++).
You could use Windows::Foundation::Collections::IVector<float>^ for the signatures. I could not test this as I don't have the compiler at hand.
Hey guys I managed to get this working so I thought I'll post the code. The header file goes like this:
public:
property Windows::Foundation::Collections::IVector<int>^ num{
void set(Windows::Foundation::Collections::IVector<int>^ e){
NUM = safe_cast<Platform::Collections::Vector<int>^>(e);
};
Windows::Foundation::Collections::IVector<int>^ get(){
return NUM;
};
};
private:
Platform::Collections::Vector<int>^ NUM;
And in the .cpp file the code is:
num = ref new Vector<int>;
num->Append(5);
num->Append(54);
TextBox1->Text = num->GetAt(0).ToString() + "\n" + num->GetAt(1).ToString();
The result will have written the values 5 and 54 to a TextBox.
I have three projects under another project of which each contains one namespace. Now among them I need to call a class which is under a namespace in visual studio 2008. Please don't ask me to add the dependencies to the main project so that I can access the namespace and all the classes in that just like local namespace which I can't do due to some restrictions. Tell me something like derived class concept so that I can access that class.
The LanguageTable class which I want to call is as follows:
#define GFX_LANGUAGE_MAX 20
namespace gfx_viewer_win32
{
public ref class LanguageTable
{
public:
static Dictionary<String ^, List<String ^>^> ^ language_string_table;
static array<String ^> ^language_string_id;
LanguageTable(void)
{
}
~LanguageTable(void)
{
}
};
}
The place from where i want to call LanguageTable class is as follows:
#pragma once
using namespace gfx_coder_prj_parser;
namespace Code_generator
{
public ref class CCodeGenerator : CCodeParserMultiLayer
{
CCodeGenerator(void)
{
}
~CCodeGenerator(void)
{
}
/*============I want to call LanguageTable class from here==========*/
};
}
If you don't want to add the assembly of LanguageTable class as a reference, you can reach it by System.Reflection. First load the assembly and create an instance of LanguageTable and now you can call methods,access properties of it by searching for by their names like
Assembly ^ langTableAssembly = Assembly::Load("assembly_name" or binary_data_of_assembly );
object ^ langTable = langTableAssembly->CreateInstance("gfx_viewer_win32::LanguageTable", ...with_other_params);
Type ^ langTableType = langTable->GetType();
MemberInfo ^ langStringID = langTableType.GetMember("language_string_id")[0];
MethodInfo ^ someMethod = langTableType.GetMethod("method_name");
someMethod->Invoke(langTable, ...other_params);
It is not a good approach though. It depends on the names, any change of the names (via refactoring etc.) you have to fix the code above. And I cannot say, this has the best performance.
Lastly, once loaded, the assembly of LanguageTable will not be unloaded during the execution of program. If you wish to unload it, this is another story called "playing with Appdomains".
Here and here are some links to begin with.
I am trying to create a Managed C++/CLI object in unmanaged code.
Is this possible?
If so, am I doing it right? see code below
#include <vcclr.h>
#include <ManagedClass.h>
// compiled with /clr
namespace X
{
class UnmanagedClass
{
UnmanagedClass(){}
~UnmanagedClass(){}
gcroot<Y::ManagedClass^> m_guiControl;
void functionA()
{
m_guiControl = new gcroot<Y::ManagedClass^>;
}
}
}
// compiled into Managed dll with /clr
// in file ManagedClass.h in a separate project
using namespace System::ComponentModel;
// more usings here ..etc
namespace Y {
public ref class ManagedClass : public System::Windows::Forms::UserControl
{
// implementation here
}
}
When I compile the UnmanagedClass source file, I keep getting a whole lot of errors with the first one being error C2039: 'ComponentModel' : is not a member of 'System'. How come it is not recognising ComponentModel?
I thought this was suppose to be IJW (it just works) ;-)
Here's an example for a wrapper:
class UnmanagedClass
{
gcroot<ManagedClass^> m_managed;
public:
UnmanagedClass()
{
m_managed = gcnew ManagedClass();
}
};
Look here:
C++/CLI - Managed class to C# events
wrapper to c++/cli
Edit:
When you get an error on a using statement, and you know it's supposed to exist, It's usually because that dll isn't referenced.
Go to the projects references, choose add reference.
You can add .Net assemblies in the .Net tab. Find the one you need and add it.