RodionP
asked on
Calling C++ function from C#
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
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
ASKER
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
ASKER
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
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.InteropServ ices;
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.
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.InteropServ
namespace ConsoleApplication1
{
class Class1
{
[DllImport("TestDLL.dll")]
public static extern string Test(string p);
[STAThread]
static void Main(string[] args)
{
Console.Out.WriteLine(Test
}
}
}
================ 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.
ASKER
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...
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...
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");
}
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");
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I will try that, thank you for your response, I'll try to answer asap
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.