Feeds:
Posts
Comments

Archive for the ‘C++/CLI’ Category

As most of you already know by now, the C++ Component Extensions (or just C++/CX) introduced in Visual C++ 11 will basically use the C++/CLI syntax with minor differences. Someone asked me on Code Project what I thought of that and I replied to him, (paraphrasing here) – “Years of using an unpopular syntax to code in C++ is finally going to pay off”. I also believe that the very reason we are getting intellisense for C++/CLI now is that they had to do that for C++/CX anyway, so they (as in the VC++ team) may well have thought they’d do it for C++/CLI as well. Obviously while there are syntactic similarities, they do target entirely different data/code/memory models – so that has to be kept in mind. One of them is for garbage collected .NET while the other is for ref-counted native code/COM (WinRT). I will be blogging more on C++/CX here in the next few weeks/months. So if anyone’s interested in that stuff, stay tuned.

Read Full Post »

The future of C++/CLI

With all the unverified but reasonably believable rumors about the new Windows 8 API (Jupiter) and how it supports managed and native APIs, questions can be raised as to the need or use of C++/CLI as a Windows programming language. Well here are a few reasons why I think C++/CLI won’t go away and will continue to remain a minimally used but very important citizen in the Windows programming language world.

  • Windows 7 and Vista, and possibly XP are not going away anytime soon. Apps that run on those OSes can continue to benefit from the mixed mode capabilities of C++/CLI.
  • Even on Windows 8, assuming the core API offers managed and native versions with full functional parity, there is still the fact that 3rd party code and customer legacy code bases will continue to exist as a nice mix of managed and native libraries. So interop will still be a key requirement in any significant software attempt, and thus C++/CLI as well.
  • The next version of Visual Studio brings back support for intellisense with C++/CLI. I am pretty sure they won’t go that far without solid enough reasons to back the fact that C++/CLI will continue to have a role to play.
  • Large corporate apps may have multiple teams working together, some with managed coding skills, others with C++ skills. C++/CLI can still play a useful role to unify the different code bases for common use.

That said, I do not see C++/CLI being used as a first class managed language. Its solitary purpose would be as an interop bridge.

And does this mean I’ll write an update for my C++/CLI book? Unlikely! Even if there’s new stuff to write about, it won’t be significant enough to bring out a 2nd edition. I’d rather write an article and publish that directly. Faster, simpler, and so much more straightforward.

Read Full Post »

This question was recently asked in the MSDN forums and answered by myself, and I am blogging it here so I have a page to link to if something similar gets asked again in that or some other forum. The OP had a C# caller that called a mixed-mode DLL’s method that took 3 arguments of type int%. This mixed-mode method then called a native function that took 3 arguments of type int* and modified all three of them. The OP was confused as to how to pass the int% values passed from C# to the native method. The central issue was that although int is a value type, int% is a tracking reference and needs to be pinned first. Once you do that, you just pass it to the native method. Example code snippet:

void nativefunc(int *p1, int *p2, int *p3)
{
  // . . .
}

void managedfunc([Out]int% mp1, [Out]int% mp2, [Out]int% mp3)
{
  pin_ptr<int> p1 = &mp1;
  pin_ptr<int> p2 = &mp2;
  pin_ptr<int> p3 = &mp3;

  nativefunc(p1, p2, p3);
}

Read Full Post »

This question was recently asked in one of the Code Project forums. Here’s what you need to do:

generic<typename T> ref class GenericList
{
public:
    T GetNext()
    {
        T temp = T();
        return temp;
    }
};

In the above code snippet T() is identical to default(T) in C#, and will generate the exact same msil.

Read Full Post »

I got asked this in one of my article forums, and thought I’d blog about it here so I can just direct people to a single URL if the question comes up again. Here’s how you’d do it (I used the example property the OP used):

//The header file

ref class Test
{
public:
  property Byte default[int]
  {
    Byte get(int index);
    void set(int index, Byte value);
  }

  //...
};

//The cpp file

Byte Test::default::get(int index)
{
  return 0;
}

void Test::default::set(int index, Byte value)
{
}

//...

Read Full Post »

I just reported this bug on Connect :

.NET 4.0 supports covariance and contravariance in delegates and interfaces. Unfortunately, C++/CLI does not support this as of VC++ 2010 RTM. Considering that the most popular use for C++/CLI today is as an interop language, the compiler not supporting a feature that’s going to be heavily used in the BCL and in new C# libraries is a very serious problem. It will impose limits on how effective C++/CLI will be as an interop-language.

If you think this is a serious enough problem, please vote the bug up so it gets more attention. Thank you.

Read Full Post »

The lack of intellisense has been the biggest show-stopper for using VC++ 2010 for any managed or mixed mode programming. Many people could not make the upgrade from VC++ 2008 for this very reason. Fortunately, the latest version of Visual Assist X from Whole Tomato Software provides fully functional intellisense for C++/CLI code! VA has always been a truly impressive add-in for VC++ users for a decade or so now, and with this update they make it obvious why they are still one of the most popular and most useful add-ins for Visual C++.

For anyone doing C++/CLI in VS 2010 and totally frustrated with the Notepad like editing experience, or for anyone holding off on upgrading to VS 2010, I strongly recommend Visual Assist X. I’ve been using it for a couple of weeks now and I have not noticed any performance issues with VS 2010 although I am on a very fast machine with heaps of memory. That said, there are several other improvements and refactoring features that Visual Assist X provides but I was primarily evaluating it for the C++/CLI intellisense.

Read Full Post »

Pon Sayasith emailed me a couple of weeks ago saying he’d bought my C++/CLI book and then went on to ask me what I thought of a mixed mode static library that has a managed class and a native wrapper, that is then consumed by a native C++ app. My first reaction (which turned out to be wrong) was that this would not be possible. But I was basically over-thinking there.

My initial thought was that when you have a C++ project with say 1 cpp file compiled as /clr, you are still forced to change project settings to match those that support the /clr switch. But when you link with a lib with a /clr compiled cpp file, your native project settings are not changed. I wasn’t sure if that was alright to do and whether the compiler was unaware of the fact that the lib needs managed support.

But I did a quick test and apparently, once the compiler sees that a linker lib is mixed-mode, then it knows how to handle that and the main exe is itself generated as a .NET executable (with mscoree.dll called and all that). This actually has an advantage in that you don’t need to tweak project settings to support /clr compilation.

So if you want to avoid tweaking your main project’s settings just to enable /clr compilation on a couple of cpp files, then this approach is an excellent workaround for you. The static lib project will need to have its project settings tweaked for /clr compilation (even for selective cpp files), but your main project settings remain unchanged, and just as you want it.

Read Full Post »

This question or a similar variation pops up in the forums once in a while. The core problem is that while null terminated char arrays can be marshaled to a System.String fairly easily, with other unmanaged arrays the marshaller cannot know for sure what size of array to create. The solution is to marshal the argument as an IntPtr and then in the calling code, the user can manually create a managed array and copy the data into it. This assumes that the unmanaged API has a size parameter (which it invariably does) that indicates the length of the unmanaged array. Here's some example code that shows how this is done:

C++ code

typedef long (CALLBACK * READDATA)(unsigned char * data, int length);

extern "C" __declspec(dllexport)  void __stdcall SomeFunc(READDATA rd)
{
 unsigned char data[5] = {'a', 'b', 'c', 'd', 'e'};
 rd(data, 5);
}

And here's the calling code:

C# code

delegate int ReadDataDelegate(IntPtr data, int len);

[DllImport("SimpleLib.dll")]
static extern void SomeFunc(ReadDataDelegate d);

private static void CallNativeWithCallback()
{
    ReadDataDelegate newCB = new ReadDataDelegate((data, len) =>
    {
        byte[] array = new byte[len];
        Marshal.Copy(data, array, 0, len);
        foreach (byte b in array)
        {
            Console.WriteLine((char)b);
        }
        Console.WriteLine();
        return 0;
    });
    SomeFunc(newCB);
}

Read Full Post »

There was a very interesting thread on Code Project’s C++/CLI forum last week. Here’s the link to the thread :

The gist of the post is that the C++/CLI compiler was not recognizing an overloaded unary operator defined in an interface while it could do so when the interface was changed to a base class.

Here’s some example code that reproduces the problem :

 interface class Base
 {
 public:
  static int operator * (Base^) { return 99; }
  static int operator + (Base^) { return 99; }
 };

 ref class Derived : Base
 {
 };

  static void Foo()
  {
    Derived^ d = gcnew Derived();

    int x = *d;
    int y = +d; 

Both those lines will not compile. In the case of the * operator you get a confusing error because the compiler assumes you are trying to dereference the handle.

Error 1 error C2440: 'initializing' : cannot convert from
    'Test::Derived' to 'int'
Error 2 error C2675: unary '+' : 'Test::Derived ^' does not define this
    operator or a conversion to a type acceptable to the predefined
    operator

Changing Base from an interface class to a ref class works fine. I believe this is a compiler bug because the ECMA language specification says this in section 25.2 Interface members:

"An interface definition can declare zero or more members. The members of an interface shall be static data members, instance or static functions, a static constructor, instance or static properties, instance or static events, operator functions, or nested types of any kind. An interface shall not contain instance data members, instance constructors, or a finalizer."

The workaround right now is to do this :

int x = Base::operator *(d);
int y = Base::operator +(d);
Affected versions:

This bug exists in VS 2008 as well as in VS 2010 RC.

Read Full Post »

Older Posts »

Follow

Get every new post delivered to your Inbox.