Passing Data Between C# and C++/CLI DLL

2673
5
09-01-2010 05:19 AM
MattMoyles
New Contributor III
The application we are developing requires many small looping operations to be run on feature classes and these operations must process hundreds of thousands of points in a few seconds.  Because of this we decided it might be worth looking into using a Managed C++/CLI proxy class as explained at the end of this page: http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//0001000000wm000000 Apparently it can decrease runtimes on repetive operations quite substantially since in C++ you can skip the interop layer between .NET and COM.

I can load my C++/CLI into my C# app fine and access the public methods and what not, but what I can't seem to do is pass any sort of meaningful data between the two.  To better illustrate here is some code:

C++ ProxyClass
// ProxyClass.h

#pragma once

#include <comdef.h>
#include <comutil.h>

using namespace System;
using namespace System::Runtime::InteropServices;

namespace ArcProxy {

    public ref class ArcProxy
    {
    public:
        ArcProxy()
        {
            ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
            //ESRI_SET_VERSION(esriArcGISEngine);
        }

        ~ArcProxy()
        {
            ::CoUninitialize();
        }

        void PointOperations(IFeatureClass % ipPointFeatures, long numPoints)
        {
            IFeatureCursor *cur;
            VARIANT v;

            //IFeatureClass* fc = (IFeatureClass *)ipPointFeatures;            
            //fc->GetFeatures(v, true, &cur);
            ipPointFeatures.GetFeatures(v, true, &cur);
            
            //return ipPointFeatures;
        }

        int test() { return 2;}
    };
}


Snippet from the C# app (sourceFeatureClass is an IFeatureClass)
                ArcProxy.ArcProxy proxy = new ArcProxy.ArcProxy();

                unsafe
                {
                    proxy.PointOperations(ref sourceFeatureClass, 100000);
                }


I've tried to mess with a few different approaches after some goggling like using the Marshal class and IntPtr but I can't seem to get it working.  C++/CLI dll compiles fine but the C# complains that

Error    1    The best overloaded method match for 'ArcProxy.ArcProxy.PointOperations(ref IFeatureClass, int)' has some invalid arguments

Error    2    Argument '1': cannot convert from 'ESRI.ArcGIS.Geodatabase.IFeatureClass' to 'ref IFeatureClass'

Has anyone successfully implemented a C++/CLI proxy class in their application? Or if anyone can provide any insight I would very much appreciate it.
0 Kudos
5 Replies
RichardWatson
Frequent Contributor
I cannot help you with your C++/CLI problem though I have run into situations where using traditional unmanaged C++ is a better choice than using .NET.  When I have this problem I simply write a C++ ATL COM based class and use COM interop to communicate with it from .NET.
0 Kudos
ErikaDade
New Contributor III
To rlwatson-

I have used a C++ ATL COM class from a dll successfully under VS 2005/2008.  I cannot successfully create a project in VS2010 with an ATL simple object and have a public method visible from the Interface.  The ESRI walk-through applied to VS2005 when ATL was attributed.  Now the ATL auto-generated code looks different; using VS to add a method to the class doesn't achieve visibility in the interface.  The following snippet is from a VB ArcGIS extension OnClick method for a custom tool.  In the VB project (with Interop dll included as a resource), the Interface and class are recognized, but the Launch() method is not (and I see no methods in Object Browser).  Back in the C++ dll project, I can see the Launch method on the Interface class in the Object Browser. 

    Public Overrides Sub OnClick()
        Try
            Dim show As ICCTShowDlgATL
            show = New CCTShowDlgATL
            show.Launch(m_application, 500)

        Catch e As System.Exception
            MsgBox("Error from SIE DLL: " & e.Message & vbCrLf & _
            e.Source & vbCrLf & _
            "Stack Trace: " & vbCrLf & e.StackTrace)
        End Try
    End Sub

Any ideas?  I have very little understanding of ATL COM and relied previously on the walk-through to achieve success!
Thanks in advance for your help.
0 Kudos
RichardWatson
Frequent Contributor
Here is the book I use as a reference for ATL programming:

http://www.amazon.com/ATL-Internals-Working-2nd-Edition/dp/0321159624

I believe that attributed ATL is dead.  See appendix D.

I suggest that you focus on trying to create a trivial COM object using C++ and drive it from a simple shell script, i.e. not ArcMap.  One you get that right then try consuming it from ArcMap.

The book has some simple walkthroughs that you can go through.  It isn't based on VS2010 but the basic flow is the same.
0 Kudos
ErikaDade
New Contributor III
Thanks very much for replying- the book looks really helpful.

Have you got a simple script you would be willing to share that I might modify to access my class?  I haven't done that before.

Cheers!
0 Kudos
RichardWatson
Frequent Contributor
You can call CreateObject using a variety of the scripting languages.

Here is Example.wsf:

<job id="main">
<script language="VBScript">
                   set typeLib = CreateObject("NEScriptUtility.TypeLibrary")    
                   typeLib.LoadTypeLibrary("C:\Program Files\Common Files\Infragistics\UltraSuite\MSVBVM60.DLL")                                
                   WScript.Echo typeLib.Name
</script>
</job>

http://en.wikipedia.org/wiki/Windows_Script_File
0 Kudos