Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. calling a method in c++ from c#

calling a method in c++ from c#

Scheduled Pinned Locked Moved C#
csharpc++sharepointquestion
10 Posts 2 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    bonosa
    wrote on last edited by
    #1

    this is in my c++ file

    public ref class Class1
    {
    public:
    int read_file
    (const char * file_path, /* Path to file */
    hdf_call_vars_t & ret_vals) ;

    };
    

    and from c# I call it like so (unsafe code)

    hdf\_call\_vars\_t ret\_vals;
    
            string str = "C:\\\\a.h5";
            byte\[\] bytes = Encoding.ASCII.GetBytes(str);
    
    
    
                fixed (byte\* p = bytes)
                {
                    sbyte\* sp = (sbyte\*)p;
                    
                    DoAT.Class1 cl = new DoAT.Class1();
    
                    cl.read\_file(sp,  ref ret\_vals);
    

    It does not compile sayiing the c++ is expecting a pointer to a structure. I thought making it an & is the same as passing by ref? Input appreciated. thanks, sb p.s. the c++ is a managed dll and I add it as a reference in the c# program.

    N 1 Reply Last reply
    0
    • B bonosa

      this is in my c++ file

      public ref class Class1
      {
      public:
      int read_file
      (const char * file_path, /* Path to file */
      hdf_call_vars_t & ret_vals) ;

      };
      

      and from c# I call it like so (unsafe code)

      hdf\_call\_vars\_t ret\_vals;
      
              string str = "C:\\\\a.h5";
              byte\[\] bytes = Encoding.ASCII.GetBytes(str);
      
      
      
                  fixed (byte\* p = bytes)
                  {
                      sbyte\* sp = (sbyte\*)p;
                      
                      DoAT.Class1 cl = new DoAT.Class1();
      
                      cl.read\_file(sp,  ref ret\_vals);
      

      It does not compile sayiing the c++ is expecting a pointer to a structure. I thought making it an & is the same as passing by ref? Input appreciated. thanks, sb p.s. the c++ is a managed dll and I add it as a reference in the c# program.

      N Offline
      N Offline
      N a v a n e e t h
      wrote on last edited by
      #2

      bonosa wrote:

      It does not compile sayiing the c++ is expecting a pointer to a structure. I thought making it an & is the same as passing by ref?

      It is indeed passing by ref. How is your hdf_call_vars_t looks like? For me the following code compiles and runs fine.

      struct hdf_call_vars_t {
      int foo;
      };

      public ref class Class1 {
      public:
      int read_file(const char * file_path, hdf_call_vars_t & ret_vals);
      };

      int Class1::read_file(const char * file_path, hdf_call_vars_t & ret_vals)
      {
      Console::WriteLine(ret_vals.foo);
      return 1;
      }

      int main(array ^args)
      {
      hdf_call_vars_t instance;
      instance.foo = 10;
      Class1^ c = gcnew Class1;
      c->read_file("A string", instance);
      return 0;
      }

      If you are using C++/CLI, you don't have to use unsafe code in C#. Just wrap the C++ specific code in C++/CLI and return well defined managed objects which can be consumed directly from C#. After all, that's what C++/CLI is best at.

      Best wishes, Navaneeth

      B 2 Replies Last reply
      0
      • N N a v a n e e t h

        bonosa wrote:

        It does not compile sayiing the c++ is expecting a pointer to a structure. I thought making it an & is the same as passing by ref?

        It is indeed passing by ref. How is your hdf_call_vars_t looks like? For me the following code compiles and runs fine.

        struct hdf_call_vars_t {
        int foo;
        };

        public ref class Class1 {
        public:
        int read_file(const char * file_path, hdf_call_vars_t & ret_vals);
        };

        int Class1::read_file(const char * file_path, hdf_call_vars_t & ret_vals)
        {
        Console::WriteLine(ret_vals.foo);
        return 1;
        }

        int main(array ^args)
        {
        hdf_call_vars_t instance;
        instance.foo = 10;
        Class1^ c = gcnew Class1;
        c->read_file("A string", instance);
        return 0;
        }

        If you are using C++/CLI, you don't have to use unsafe code in C#. Just wrap the C++ specific code in C++/CLI and return well defined managed objects which can be consumed directly from C#. After all, that's what C++/CLI is best at.

        Best wishes, Navaneeth

        B Offline
        B Offline
        bonosa
        wrote on last edited by
        #3

        thank you Navaneeth. The struct is [StructLayout(LayoutKind.Sequential, Pack = 1)] /* Returned values from read_file */ unsafe struct hdf_call_vars_t { public channel_vars p_vars; public channel_vars s_vars; FILE_VERSION file_vers; public int fetch_n; public s_line_header_t * n_addr; /* malloc'd address of n data */ public UInt32 n_lines; c_file_header_t hdr; } I added the structlayout line in the c# world. Mine still doesn't compile. I'm new to this so I don't know what is meant by wrapping unsafe code in c++ yet. thanks so much, saroj

        N 1 Reply Last reply
        0
        • N N a v a n e e t h

          bonosa wrote:

          It does not compile sayiing the c++ is expecting a pointer to a structure. I thought making it an & is the same as passing by ref?

          It is indeed passing by ref. How is your hdf_call_vars_t looks like? For me the following code compiles and runs fine.

          struct hdf_call_vars_t {
          int foo;
          };

          public ref class Class1 {
          public:
          int read_file(const char * file_path, hdf_call_vars_t & ret_vals);
          };

          int Class1::read_file(const char * file_path, hdf_call_vars_t & ret_vals)
          {
          Console::WriteLine(ret_vals.foo);
          return 1;
          }

          int main(array ^args)
          {
          hdf_call_vars_t instance;
          instance.foo = 10;
          Class1^ c = gcnew Class1;
          c->read_file("A string", instance);
          return 0;
          }

          If you are using C++/CLI, you don't have to use unsafe code in C#. Just wrap the C++ specific code in C++/CLI and return well defined managed objects which can be consumed directly from C#. After all, that's what C++/CLI is best at.

          Best wishes, Navaneeth

          B Offline
          B Offline
          bonosa
          wrote on last edited by
          #4

          Navaneeth, your Main is written in C++ right? My main is in C# thanks!

          1 Reply Last reply
          0
          • B bonosa

            thank you Navaneeth. The struct is [StructLayout(LayoutKind.Sequential, Pack = 1)] /* Returned values from read_file */ unsafe struct hdf_call_vars_t { public channel_vars p_vars; public channel_vars s_vars; FILE_VERSION file_vers; public int fetch_n; public s_line_header_t * n_addr; /* malloc'd address of n data */ public UInt32 n_lines; c_file_header_t hdr; } I added the structlayout line in the c# world. Mine still doesn't compile. I'm new to this so I don't know what is meant by wrapping unsafe code in c++ yet. thanks so much, saroj

            N Offline
            N Offline
            N a v a n e e t h
            wrote on last edited by
            #5

            Wrapping native objects means, you create a managed class in C++/CLI and hide your hdf_call_vars_t struct inside this managed class. Your library will only deal with this managed object and at the C# side you only have to deal with this managed object. This approach hides all the complexities of using native structs and simplifies your library's interface. Here is working example of wrapping native object in a managed object.

            // ClassLibrary.h

            using namespace System;

            namespace Example {

            // Native struct
            struct hdf\_call\_vars\_t {
            	int foo;
            };
            
            // This wraps the native hdf\_call\_vars\_t and provides managed class
            public ref class HdfCallVars
            {
            private:
            	hdf\_call\_vars\_t\* native;
            
            public:
            	HdfCallVars()
            	{
            		native = new hdf\_call\_vars\_t;
            	}
            
            	property int Foo
            	{
            		int get()
            		{
            			return native->foo;
            		}
            		void set(int value)
            		{
            			native->foo = value;
            		}
            	}
            };
            
            
            // This is your libraries main class
            public ref class YourLibrary {
            public:
            	// This method now takes managed objects
            	int ReadFile(String^ file\_path, HdfCallVars^ ret\_vals)
            	{
            		// your code goes here
            		return ret\_vals->Foo;
            	}
            };
            

            }

            To use this library from a C# application,

            using System;
            using Example;

            namespace ConsoleApplication1
            {
            class Program
            {
            static void Main(string[] args)
            {
            HdfCallVars vars = new HdfCallVars();
            vars.Foo = 10; // Doing native call through well defined interface

                    YourLibrary library = new YourLibrary();
                    int status = library.ReadFile("filepath", vars);
                    Console.WriteLine(status);
                    Console.Read();
                }
            }
            

            }

            Hope that helps.

            Best wishes, Navaneeth

            B 1 Reply Last reply
            0
            • N N a v a n e e t h

              Wrapping native objects means, you create a managed class in C++/CLI and hide your hdf_call_vars_t struct inside this managed class. Your library will only deal with this managed object and at the C# side you only have to deal with this managed object. This approach hides all the complexities of using native structs and simplifies your library's interface. Here is working example of wrapping native object in a managed object.

              // ClassLibrary.h

              using namespace System;

              namespace Example {

              // Native struct
              struct hdf\_call\_vars\_t {
              	int foo;
              };
              
              // This wraps the native hdf\_call\_vars\_t and provides managed class
              public ref class HdfCallVars
              {
              private:
              	hdf\_call\_vars\_t\* native;
              
              public:
              	HdfCallVars()
              	{
              		native = new hdf\_call\_vars\_t;
              	}
              
              	property int Foo
              	{
              		int get()
              		{
              			return native->foo;
              		}
              		void set(int value)
              		{
              			native->foo = value;
              		}
              	}
              };
              
              
              // This is your libraries main class
              public ref class YourLibrary {
              public:
              	// This method now takes managed objects
              	int ReadFile(String^ file\_path, HdfCallVars^ ret\_vals)
              	{
              		// your code goes here
              		return ret\_vals->Foo;
              	}
              };
              

              }

              To use this library from a C# application,

              using System;
              using Example;

              namespace ConsoleApplication1
              {
              class Program
              {
              static void Main(string[] args)
              {
              HdfCallVars vars = new HdfCallVars();
              vars.Foo = 10; // Doing native call through well defined interface

                      YourLibrary library = new YourLibrary();
                      int status = library.ReadFile("filepath", vars);
                      Console.WriteLine(status);
                      Console.Read();
                  }
              }
              

              }

              Hope that helps.

              Best wishes, Navaneeth

              B Offline
              B Offline
              bonosa
              wrote on last edited by
              #6

              Thank you so very much for taking the time to answer in such detail, Navaneeth! I learned a lot from your code. I do have a question though. Since my hdf_call_vars_t is a complex structure containing members whiuch are instances of other structs, how do I treat those? For example, it has a member 'struct channel_vars p_data.' A channel_vars type struct instance contains in it ints, doubles, enums and a void * . I'll of course create get set accessors for Channel_vars as you have shown for the int foo in your example.But do I need to make Channel Vars a wrapper class also? thank you, saroj

              N 1 Reply Last reply
              0
              • B bonosa

                Thank you so very much for taking the time to answer in such detail, Navaneeth! I learned a lot from your code. I do have a question though. Since my hdf_call_vars_t is a complex structure containing members whiuch are instances of other structs, how do I treat those? For example, it has a member 'struct channel_vars p_data.' A channel_vars type struct instance contains in it ints, doubles, enums and a void * . I'll of course create get set accessors for Channel_vars as you have shown for the int foo in your example.But do I need to make Channel Vars a wrapper class also? thank you, saroj

                N Offline
                N Offline
                N a v a n e e t h
                wrote on last edited by
                #7

                bonosa wrote:

                But do I need to make Channel Vars a wrapper class also?

                If that is something which user has to create, you need to make it a managed class. All your internal structures don't need to be wrapped because you handle the creation of those inside your main managed object.

                Best wishes, Navaneeth

                B 1 Reply Last reply
                0
                • N N a v a n e e t h

                  bonosa wrote:

                  But do I need to make Channel Vars a wrapper class also?

                  If that is something which user has to create, you need to make it a managed class. All your internal structures don't need to be wrapped because you handle the creation of those inside your main managed object.

                  Best wishes, Navaneeth

                  B Offline
                  B Offline
                  bonosa
                  wrote on last edited by
                  #8

                  Thanks Navaneeth, that almost compiled! Now I have a problem!

                  int atClass1::read_file
                  (String^ file_path, /* Path tofile */
                  HdfCallVars % ret_vals)

                  I did the above as you advised. However ret_vals has to be fed to an HDF5 function which needs a void* as one of it's arguments. So I am stuck at the following line of code not knowing what to do:

                  /* Iterate through the links, filling in needed data as discovered. */
                  io_err = H5Literate (group_id, H5_INDEX_NAME, H5_ITER_NATIVE,

                  	       &i, get\_data,  (void\*)&ret\_vals);
                  

                  the compiler doesn't like (void*)&ret_vals.... What to do? thanks, saroj

                  N 2 Replies Last reply
                  0
                  • B bonosa

                    Thanks Navaneeth, that almost compiled! Now I have a problem!

                    int atClass1::read_file
                    (String^ file_path, /* Path tofile */
                    HdfCallVars % ret_vals)

                    I did the above as you advised. However ret_vals has to be fed to an HDF5 function which needs a void* as one of it's arguments. So I am stuck at the following line of code not knowing what to do:

                    /* Iterate through the links, filling in needed data as discovered. */
                    io_err = H5Literate (group_id, H5_INDEX_NAME, H5_ITER_NATIVE,

                    	       &i, get\_data,  (void\*)&ret\_vals);
                    

                    the compiler doesn't like (void*)&ret_vals.... What to do? thanks, saroj

                    N Offline
                    N Offline
                    N a v a n e e t h
                    wrote on last edited by
                    #9

                    bonosa wrote:

                    the compiler doesn't like (void*)&ret_vals....

                    Add a method to HdfCallVars so that it can give you the underlying native struct.

                    Best wishes, Navaneeth

                    1 Reply Last reply
                    0
                    • B bonosa

                      Thanks Navaneeth, that almost compiled! Now I have a problem!

                      int atClass1::read_file
                      (String^ file_path, /* Path tofile */
                      HdfCallVars % ret_vals)

                      I did the above as you advised. However ret_vals has to be fed to an HDF5 function which needs a void* as one of it's arguments. So I am stuck at the following line of code not knowing what to do:

                      /* Iterate through the links, filling in needed data as discovered. */
                      io_err = H5Literate (group_id, H5_INDEX_NAME, H5_ITER_NATIVE,

                      	       &i, get\_data,  (void\*)&ret\_vals);
                      

                      the compiler doesn't like (void*)&ret_vals.... What to do? thanks, saroj

                      N Offline
                      N Offline
                      N a v a n e e t h
                      wrote on last edited by
                      #10

                      I wrote a blog post which covers the topic in detail. Take a look at this[^].

                      Best wishes, Navaneeth

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups