New to coding and having trouble with "identifier "string" is undefined" error - c++-cli

#include "MyForm.h"
using namespace System::Windows::Forms;
[STAThread];
void main(array<string^>^ args)
{
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Organizer::MyForm form;
Application::Run(%form);
}
`
I keep getting the error "identifier "string" is undefined"
how can i fix this? im new to coding and have minimal knowledge, any help is appreciated

The .Net managed System::String class starts with a capital "S".
You'll also need the namespace System:: or a using namespace System; directive at the top of the file. (Which might already be there, and you just didn't copy it to the web.)
Now, that said: If you're new to coding, please do yourself a favor and don't start with C++/CLI. Either start with C#, or with plain C++. C++/CLI is intended for .Net managed code to interact with unmanaged C/C++ code. It has all the complexities of C#, C++, and a few of its own, and is therefore not a good language to learn with.

Related

What does the IntelliSense error "public data members are not allowed in non-value types" mean?

I'm taking over a C++ CLI project and one of the files, StartScreen.xaml.h, is throwing an IntelliSense error in Visual Studio 2013. Here's a fragment of the code:
public ref class StartScreen sealed
{
public:
StartScreen();
void SetApp(App^ app);
void ShowProgressRing();
void HideProgressRing();
internal:
static float imagePercentage;
....
It's that last line that's causing the problem. imagePercentage throws the error
108 IntelliSense: public data members are not allowed in non-value types
What does this mean and how (if at all - it compiles without compiler errors) should I fix it?
I would guess it is just a bug in IntelliSense. C++/CLI and C++/CX share a syntax, but it seems that there are some rules that are different. In this case, C++/CX doesn't allow public/internal fields:
http://social.msdn.microsoft.com/Forums/windowsapps/en-US/20db7069-3e49-4772-8b9a-0c80490e0dea/error-c3984-a-nonvalue-type-cannot-have-any-public-data-members?forum=winappswithnativecode
http://msdn.microsoft.com/en-us/library/windows/apps/hh699870
C++/CLI has no such restriction (that's why it compiles for you). The Intellisense is probably just (incorrectly) sharing this rule between both C++/CLI and C++/CX.
If you really do want an internally visible field, I would just ignore the Intellisense. If it bothers you, and you can change it to a property, then that's your workaround.

Calling c# code from managed c++ crashes

I have an unmanaged c++ DLL that calls c# code through a managed c++ wrapper. The unmanaged c++ DLL is a plug-in for some application (outside my control). When this application calls the unmanaged c++ DLL everything works fine until the managed c++ code tries to use the c# code. Then it crashes.
I have written a test application that does the same thing as the application, that is, it calls the unmanaged c++ DLL. This works fine.
The code is as simple as it could be:
unmanaged c++:
extern "C" __declspec(dllexport) void UnmanagedMethodCalledUponByApplication()
{
new Bridge();
}
managed c++:
Bridge::Brigde()
{
gcnew Managed(); // This line crashes
}
c#:
public class Managed
{
}
I have tried to add a try-catch (...) block around the problematic line but it doesn't catch the error.
If I replace the gcnew Managed(); line with MessageBox::Show("Alive!"); it works fine. So my guess is that something is wrong with my c# project settings.
I have tried to compile it with different platforms (Any CPU and x86). I have tried to change target framework. I have tried to call a static method in Managed instead of using gcnew. Still crashing.
Any ideas what might be the problem?
Update:
After advise in comments and answer, I attached the debugger. Now I see that I get a System.IO.FileNotFoundException saying that the managed DLL (or one of its dependencies) can't be found.
Here's a guess: The DLLs are placed together, but they are not located in the current directory. The unmanaged c++ DLL is loaded correctly since the main application specifies the path to it. The managed c++ is actually a lib, so that code works fine as well. But when the managed c++ tries to load the c# DLL it looks for it in the wrong directory.
Update:
The way to fix this is to load the c# DLL dynamically, using reflection.
extern "C" __declspec(dllexport)
Yes, that's a cheap and easy way to get the compiler to generate the required stub that loads and initializes the CLR so it can execute managed code. Problem is, it doesn't do anything reasonable to deal with exceptions thrown by managed code. And managed code likes throwing exceptions, they are a terrific trouble-shooting tool. That stops being terrific when there's no way for you to retrieve the exception information.
The best you could possibly do from native code is use the __try/__except keywords to catch the managed exception. Exception code is 0xe0434f4d. But that still doesn't give you access to the information you need, the exception message and the holy stack trace.
You can debug it. Project + Properties, Debugging, change the Debugger Type to "Mixed". Then Debug + Exceptions, tick the Thrown checkbox for CLR Exceptions. The debugger stops when the exception is thrown so you can see what's wrong.
Getting decent diagnostics after you shipped your code requires a better interop mechanism. Like using COM interop or hosting the CLR yourself.

Using the word "Windows" as part of your own namespace in Metro style apps

If you try to use Windows as part of your own namespace in Metro-style apps (e.g. MyCompany.Windows) it seems that it throws compiler(s) off, because they start looking for WinRT stuff under your namespace rather than Windows.*.
For example, if you create a blank Windows Metro style app named App1 and rename App1 namespace to be App1.Windows and try to compile it you'll get an error:
The type or namespace name 'UI' does not exist in the namespace 'App1.Windows' (are you missing an assembly reference?) F:\temp\App1\App1\obj\Debug\App.g.i.cs
the top of the generated file looks like this:
namespace App1.Windows
{
#if !DISABLE_XAML_GENERATED_MAIN
public static class Program
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 4.0.0.0")]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
static void Main(string[] args)
{
Application.Start((p) => new App());
}
}
#endif
partial class App : Windows.UI.Xaml.Application
and the problem is that compiler starts looking for Windows.UI under App1.Windows.
Now this is nothing new and if you'd name your namespace App1.System before you would probably get into a similar kind of trouble at some point. The problem is that quite a lot of WPF/Silverlight/Windows Phone code out there uses MyCompany.Windows.Xyz namespaces and is probably susceptible to this kind of trouble.
Is there some guidance from Microsoft (can't seem to find one) as to what to do with these namespaces? Or maybe there are some plans on resolving this in future versions? Or am I just missing something?
I looked at this issue and we should be using global:: in the generated code. We have fixed this on our end and will be available in next release of Visual Studio.
This is a known behavior in the C# language specification. Basically whenever a namespace appears in a "using" clause, the system treats all the elements in the namespace as if they might be part of the using namespace. There are two workarounds: Remove the name "Windows" from the inner nodes in your type or remove the "using" directive.
This is unfortunately not a winrt issue, you can get the same thing to happen with pure CLR applications.

How to expose templates from a C++ to C# via C++/CLI

I want to expose a C++ library to a C# application and I decided to take the C++/CLI wrapper approach instead of P/Invoke. The problem that I am now facing is how to expose a templated class in the C++ lib to the C# application using generics.
On the C++ side I have:
template <typename T> class Someclass;
And my goal is to be able to expose the following type to the C# app
class Someclass<T> {}
So the question now is how should my C++/CLI wrapper look like. I tried the naive approach and created a templated type in C++/CLI and naturally I wasnt able to instantiate the class in C# with generic parameters. And if I expose the class as a generic class I wont be able to pass it to C++.
Disclaimer: I am a C++ newbie so please be gentle :)
I am familiar with the differences between generics and templates so no need to explain those. I have this bad feeling that what I want isn't doable, but since I am relatively new to C++ I hope I can somehow achieve it.
AFAIK: You'll have to write a C++ generic.
http://www.codeproject.com/KB/mcpp/cppcligenerics.aspx
I don't see how the C# application would even understand the template being as that is calculated at compile time, so the C# application wont see templates in the DLL.

how to use classes written in IronPython in VB.NET

I have a class (e.g. MksMath) written in IronPython using SharpDevelop 3.2. After compiling it for class library, it produced the following output:
IronPython.dll
IronPython.Modules.dll
Microsoft.Dynamic.dll
Microsoft.Scripting.Core.dll
Microsoft.Scripting.Debugging.dll
Microsoft.Scripting.dll
Microsoft.Scripting.ExtensionAttribute.dll
mksmath.dll
If I try to add reference to all above dll and import "MksMath", I am unable to access it. The vbc is throwing the following error:
Namespace or type specified in the Imports 'MksMath' doesn't contain any public member or cannot be found. Make sure the namespace or the type is defined and contains at least one public member. Make sure the imported element name doesn't use any aliases.
I am new to IronPython. Kindly advise how to use this class in my vb.net code?
I post here my answer that I posted to IronPythopn mailing list :-)
You cannot use mksmath.dll directly from VB (see Compiling Python code into an assembly) so you have to host IronPython engine in your VB app and use mksmath.dll from the engine. See Using Compiled Python Classes from .NET/CSharp IP 2.6 for example (in C#).
Here is a link that I think may solve the issue. http://msmvps.com/blogs/theproblemsolver/archive/2008/08/14/calling-ironpython-functions-from-net.aspx