?
Solved

Calling C++ function from C#

Posted on 2005-04-16
10
Medium Priority
?
3,070 Views
Last Modified: 2008-01-09
Hi, I have a C# application that has to call one C++ function

here is the code that I want to use from C#:

[DllImport("DllTest.dll")]
public static extern string Test(string param);

[STAThread]
static void Main()
{
      string tmp =Test("test1");
      Console.Out.WriteLine(tmp);
}


Here is what I would write in DllTest if it was C#

public static extern string Test(string inParam)
{
      return inParam + " SPECIAL";
}





Can you please give me an equivalent in C++ so that function will port to C# without a problem

Thank you
0
Comment
Question by:RodionP
  • 4
  • 3
8 Comments
 
LVL 3

Expert Comment

by:Octabun
ID: 13798671
The function you request looks like

      static public __gc class Class1
      {
      public:
            static String * Test(String * t) {
                  String * p = new String("Special");
                  return t->Concat(t, p);
            }
      };

please note that it uses managed extencions and should be compiled to a .NET assembly. You do not need

[DllImport("DllTest.dll")]
public static extern string Test(string param);

to access a .NET assembly containing C++ code. Just add the assembly to project references.

If you need a function in an unmanaged C++ dll to return a managed class, which can be the case since you use the DLllImport attribute, then it is impossible because the unmanaged DLL cannot access CLR and create a new instance of a managed class.
0
 
LVL 1

Author Comment

by:RodionP
ID: 13799017
This is C++ made by Visual Studio 6, meaning, no managed code, that is why I need to use DllImport, I need plain C++/ANSI C code
0
 
LVL 1

Author Comment

by:RodionP
ID: 13800162
I do not need to create an instance of unmanaged class, I need to call an external function, a static function, just some function written in unmanaged code
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 3

Expert Comment

by:Octabun
ID: 13800705
Aha, you want the call to "just work", without thinking much about what is going on. Yes, Microsoft has the "it just works" interop approach.

In C++ DLL you create a function

================ C++ code (C, actually)

char buf [100];

char * __cdecl Test (char * p) {
      size_t n = strlen(p);
            memcpy(buf, p, n);
      char tmp [] = "SPECIAL";
      memcpy(&buf[n], tmp, 7);
      return buf;
}

================ C++ code ends

Export it with the def file

================ TestDLL.def

; TestDLL.def : Declares the module parameters for the DLL.

LIBRARY      "TestDLL"

EXPORTS
    ; Explicit exports can go here
    Test  @1

================ TestDLL.def ends

copy TestDLL.dll to the folder your C# app is compiled to, and call Test in C# as

================ Class1.cs

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
      class Class1
      {
        [DllImport("TestDLL.dll")]
        public static extern string Test(string p);

        [STAThread]
            static void Main(string[] args)
            {
            Console.Out.WriteLine(Test("Test1"));
            }
      }
}

================ Class1.cs ends

Behind the scenes, Interop converts C# System.String to char*, marshalls it to test(), and creates System.String out of the returned char*.

You may also read "extern (C#)" help topic. Please note that "Here is what I would write in DllTest if it was C#" part of your request is not satisfied. Test() does not do what you requested, it just looks like doing it.  
0
 
LVL 1

Author Comment

by:RodionP
ID: 13801403
No it does not work for some reason,

I am not a C++ developer, but I have this C++ code that I have to port to my C# code, that C++ code is written in Visual Studio 6, I need to be able to call 1 function from all that C++ code, and it is a very simple function, it takes string as a parameter and returns string as a parameter, I tried using above example and it keeps telling me that it cannot find an entry point.

Please, assume I am stupid and explain in details, all I care is to pass a string down to C++ code and retrieve a string that that C++ code produces.

I raised the points to a maximum...
0
 
LVL 6

Expert Comment

by:melodiesoflife
ID: 13804106
Hi RodionP

First of all, The keyword string for VC ++ 6.0 isn't: string. You must use "CString" or "char*"
2nd: You dll code don't have Dll entry point.

Here is the example for you to create Win32 dll in VC++6.0

//*******************************//
#include "stdafx.h"
// Entry point function.
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                               )
{
    switch (ul_reason_for_call)
      {
            case DLL_PROCESS_ATTACH:
            case DLL_THREAD_ATTACH:
            case DLL_THREAD_DETACH:
            case DLL_PROCESS_DETACH:
                  break;
    }
    return TRUE;
}

__declspec(dllexport) char *fnDllExample(char* cMyString)
{
      //return "Hello";
               return strcat(cMyString, " - Hello");
}

0
 
LVL 3

Accepted Solution

by:
Octabun earned 2000 total points
ID: 13804173
BTW, what fails: the example code or your code that follows the example?  Let us find out where exactly you are.

Step 1. Using interop.

The "extern (C#)" help topic shows how to call MessageBox windows function:

=== Help example starts

Example

In this example, the program receives a string from the user and displays it inside a message box. The program uses the MessageBox method imported from the User32.dll library.

using System;
using System.Runtime.InteropServices;
class MyClass
{
   [DllImport("User32.dll")]
   public static extern int MessageBox(int h, string m, string c, int type);

   public static int Main()
   {
      string myString;
      Console.Write("Enter your message: ");
      myString = Console.ReadLine();
      return MessageBox(0, myString, "My Message Box", 0);
   }
}

Sample Run

Enter your message: Where do you want to go today?
When the previous text is entered, a message box that contains the text will pop up on the screen.

==== Help exampl ends

Can you run this example?

Step 2. Passing string and getting string.

Can you run my example? It is very close to the second example in "extern (C#)", but uses the DEF file to export Test(), which is more fool proof than __declspec(dllexport).

If you cannot, then why: No C++ installed in VS.NET, no skill to create a DLL, etc.

Step 3. Calling a function in your DLL.

Possibly after the first 2 steps your problem is solved. If not:

Do you have source code for your DLL? Do you have a .h file with the definition of the function you want to call or somebody just told you what it is? Can you compile the DLL? Can you see what functions are exported from a DLL?
 
I use TotalCommander (http://www.ghisler.com) with the File Info plugin (http://physio-a.univ-tours.fr/tcplugins/) to do see the functions exported by a dll, but there should be other means also.

The problem is that there is no such thing as "string" built into C/C++. However, there are class libraries that can have classes called "String". So, it is necessary to check what EXACTLY the functon you are trying to call looks like. The "it takes string as a parameter and returns string as a parameter" description is not enough.

Where we go from here depends on what you have and can.

For example:

- if you have everything you need, check the name, declaration (should be as in the example), and the fact that the function is exported. Compile the DLL. Check that the function is actually exported. Call it from C#.

- if the function is not char * (char *), then write a wrapper around it which is and call the wrapper.

- if the function is defined like __declspec(dllexport) char * Test2 (char * p) {...}, then you may add the entry point number to C# like [DllImport("TestDLL.dll", EntryPoint="#3")].
0
 
LVL 1

Author Comment

by:RodionP
ID: 13830850
I will try that, thank you for your response, I'll try to answer asap
0

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
Hello there! As a developer I have modified and refactored the unit tests which was written by fellow developers in the past. On the course, I have gone through various misconceptions and technical challenges when it comes to implementation. I would…
This lesson discusses how to use a Mainform + Subforms in Microsoft Access to find and enter data for payments on orders. The sample data comes from a custom shop that builds and sells movable storage structures that are delivered to your property. …
Loops Section Overview
Suggested Courses
Course of the Month16 days, 1 hour left to enroll

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question