Thread: Help with using c++ class called with P/Invoke

  1. #1
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391

    Help with using c++ class called with P/Invoke

    Hi,

    I've successfully been able to call C++ function into my C# ASP.NET application using P/Invoke. However, calling and using c++ classes from my DLL has been quite troublesome. Here is a small example I'm working with:

    Default.aspx.cs:
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Runtime.InteropServices;
     
    namespace SampleWebApp{
     
        public partial class _Default : System.Web.UI.Page{
     
            [StructLayout(LayoutKind.Sequential)]
            class ClassWrapper{
     
                [DllImport("MyDll.dll")]
                public static extern Int32 getANumber();
     
                public Int32 getNum(){
     
                    return ClassWrapper.getANumber();
                }
     
                [DllImport("MyDll.dll")]
                public static extern ClassWrapper returnByRef();
            };
     
            protected void Page_Load(object sender, EventArgs e){
     
                ClassWrapper c = ClassWrapper.returnByRef(); // seems to work fine
     
                textArea.InnerHtml = c.getNum().ToString();   // Compiler complains no entry point could be found in dll for getANumber()
            }
        }
    }
    MyDll.h:
    Code:
    extern "C"{
     
        class __declspec(dllexport) myClass{
     
            public:
     
                myClass(void);
                long getANumber(void);
        };
     
        __declspec(dllexport) class myClass* returnByRef();
    }
    and MyDll.cpp:
    Code:
    #include "stdafx.h"
    #include "MyDll.h"
     
    extern "C"{
     
        __declspec(dllexport) myClass::myClass(){
     
            return;
        }
     
        __declspec(dllexport) long myClass::getANumber(){
     
            return 5;
        }
     
        __declspec(dllexport) class myClass* returnByRef(){
     
            myClass* temp = new myClass();
            return temp;
        }
    }
    Like I said, functions I've had no problems with, but I really can't figure out what to do about classes( how to intantiate and call member functions, etc.)

    Any help/guidance you can offer me is most appreciated.

    Thank You
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  2. #2
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    Well for anyone who is interested I've worked one solution out (not to say it's the best solution though)

    MyDll.h:
    Code:
    extern "C"{
     
        class __declspec(dllexport) MyClass{
     
            public:
     
                MyClass( long a, long b );
     
                long getNumA();
                long getNumB();
                long getAvg();
     
            private:
     
                long numA, numB;
        };
     
        __declspec(dllexport) class MyClass* getMyClassRef( long a, long b );
     
        __declspec(dllexport) long getNumberA( class MyClass* refToMyClass );
     
        __declspec(dllexport) long getNumberB( class MyClass* refToMyClass );
     
        __declspec(dllexport) long getAverage( class MyClass* refToMyClass );
    }
    MyDll.cpp
    Code:
    #include "stdafx.h"
    #include "MyDll.h"
     
    extern "C"{
     
        MyClass::MyClass( long a, long b )
        : numA(a_, numB(b){}
     
        long MyClass::getNumA(){
            return numA;
        }
     
        long MyClass::getNumB(){
            return numB;
        }
     
        long MyClass::getAvg(){
            return (numA+numB)/2;
        }
     
        __declspec(dllexport) class MyClass* getMyClassRef( long a, long b ){
     
            MyClass* temp = new MyClass( a, b );
            return temp;
        }
     
        __declspec(dllexport) long getNumberA( class MyClass* refToMyClass ){
     
            return refToMyClass->getNumA();
        }
     
        __declspec(dllexport) long getNumberB( class MyClass* refToMyClass ){
     
            return refToMyClass->getNumB();
        }
     
        __declspec(dllexport) long getAverage( class MyClass* refToMyClass ){
     
            return refToMyClass->getAvg();
        }
    }
    Default.aspx.cs:
    Code:
    using ...
    using System.Runtime.InteropServices;
     
    namespace SampleWebApp{
     
        public partial class _Default : System.Web.UI.Page{
     
            [StructLayout(LayoutKind.Sequential)]
            class MyWrapperClass{
     
                Int32 a, b;
     
                [DllImport("MyDll.dll")]
                public static extern MyWrapperClass getMyClassRef( Int32 x, Int32 y );
     
                [DllImport("MyDll.dll")]
                public static extern Int32 getNumberA( MyWrapperClass mwc );
     
                [DllImport("MyDll.dll")]
                public static extern Int32 getNumberB( MyWrapperClass mwc );
     
     
                [DllImport("MyDll.dll")]
                public static extern Int32 getAverage( MyWrapperClass mwc );
            };
     
            protected void Page_Load(object sender, EventArgs e){
     
                MyWrapperClass m = MyWrapperClass.getMyClassRef( 50, 100 );
                textArea1.InnerHtml = MyWrapperClass.getNumberA( m ).ToString();
                textArea2.InnerHtml = MyWrapperClass.getNumberB( m ).ToString();
                textArea3.InnerHtml = MyWrapperClass.getAverage( m ).ToString();
            }
        }
    }
    As far as I can tell, there is no way to instantiate an object declared within the DLL ( I assume because of CLR typing - but if you know differently, I'd really really like to know how you do it!)

    So I basically had to write wrappers within the DLL to achieve this effect. It certainly doesn't seem perfect to me, so please somebody show me more or give me some pointers, I really need to know everything I can about marshalling data using P/Invoke.

    Also, I read through this little gem:
    Interop with Native Libraries - Mono

    ^an excellent site with A LOT of info.

    Thank You
    Last edited by dudeomanodude; 04-10-2009 at 12:03 PM.
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  3. #3
    Registered User
    Join Date
    Jan 2009
    Posts
    31
    Is C++/CLI an option?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Inherite nonvirtual class functionality
    By DrSnuggles in forum C++ Programming
    Replies: 2
    Last Post: 04-30-2009, 01:52 PM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. structure vs class
    By sana in forum C++ Programming
    Replies: 13
    Last Post: 12-02-2002, 07:18 AM