Expose Borland C++ methods to C# - c#

I have following method in my Borland C++ code,
static bool UploadBitstream(void)
{
//Some code Implementation
}
And I'm trying to convert it to DLL and access it in C#.
What are the steps I need to follow to Convert the code DLL
and then use it in C# ??

First, you have to make sure that the methods are defined extern. Then you need to declare the method stdcall or pascal calling convention, and mark them dllexport. See code listing below (this is ancient memory for me, so pardon if I am a bit off on modern Borland C++ compilers).
// code.h
extern "C" {
#define FUNCTION __declspec(dllexport)
FUNCTION int __stdcall SomeFunction(int Value);
In the main
#include "code.h"
FUNCTION int __stdcall SomeFunction(int timesThree)
{
return timesThree * 3;
}

Once you've compiled your DLL all you should need to do in .NET to get access to it is use the DLLImport property.
public class stuff
{
[DLLImport("somedll.dll")]
public static extern void UploadBitstream();
}
If you need pointers or anything like that it gets more complicated but for void functions it's that simple.
It should be noted that once you invoke that function the dll will be loaded by your program and won't be released until your program is closed. You can dynamically load dlls but that is much more complicated. I can explain it here if you have a need.

Watch your terminology.
In your example UploadBitstream is function not a method.
If it is indeed a method in a class then it is very difficult to use classes from Borland compiled DLLs.
If your code is actually C not C++ you should be able to create a compatible DLL
for your simple C style functions with C++ Builder.
See the following SO question:
Use a dll from a c++ program. (borland c++ builder and in general)
where I list various compiler settings which will also apply to creating compatible DLLs.

Related

Proper way to return a List<String^> to a Vector<std::string> in Extern "C"?

I'm communicating between CLI and I need to return back a vector of strings from my C function. I have not done much cli between c++/c# so please tell me if there is a better way to accomplish this.
//Plugin.cpp
void PluginMain(){
ServiceClientHook();
}
//Plugin.h;
extern "C" {
vector<std::string> ServiceClientHook();
}
//ServiceClientHook.h
#include "Plugin.h"
//ServiceClientHook.cpp
string ServiceClientHook()
{
return "Foobar";
}
How do I handle ServiceClientHook()? I should add that I am using non cli on my Plugin and cli on my ServiceClientHook
Currently when I try and return a vector from 'Plugin.h': C linkage function cannot return C++ class 'std::vector>'
It sounds like you have two functions in the same C++/CLI DLL project:
PluginMain -- talks to an unmanaged EXE, maybe C++, maybe not
ServiceClientHook -- talks to a C# DLL
You don't need to do anything special at all to have these talk to each other. Get rid of the extern "C" on ServiceClientHook() and it will just work. Even though ServiceClientHook() is in a file using /clr and PluginMain is plain C++.
Now, PluginMain may need to have extern "C" and __declspec(dllexport) to help the EXE find it. But those requirements don't apply to the functions it uses.

Call C++ Dll in C#.net using dllImport

Please find the below Examples
void ExitLibrary(); // C++ function
I am able to covert to C# like below
[DllImport("VisualFOD.dll", CharSet = CharSet.Ansi)]
public static extern void ExitLibrary();
This method will be used to start the live capturing
bool StartLive(DShowLib::Grabber* f_Grabber, HDC f_hHdc, RECT f_WindowRect);
This method will be used to start the live capturing
[DllImport("TIS_UDSHL09_vc71.dll", CharSet = CharSet.Ansi)]
public static extern bool StartLive(IntPtr f_Grabber, IntPtr f_hHdc, Rectangle f_WindowRect);
I am not able to access the actual class DShowLib::Grabber as mentioned in the 2nd statement C++ function.
Do you have any idea how to declare and get the library class name?
This dll is not a COM/.Net dll to include as a reference to C# environment.
If I understand your question correctly, you won't be able to access the DShowLib::Grabber class directly in C# if it resides inside the DLL (and is accessed by a C++ header file).
Two solutions are available. Firstly, you can wrap the native DLL class in C++/CLI class, such that you can include the native C++ header files; Secondly, you can write your own DLL, where you can flatten the DLL class and P/Invoke your flatten methods.
By flattening I mean:
class C
{
void M(int i, float j);
}
The method M has to be called like:
__declspec(dllexport) BOOL __stdcall C_M(C * instance, int i, float j)
{
if (instance == nullptr)
return FALSE;
instance->M(i, j);
return TRUE;
}
However, please take into consideration comments for your question. If you can use ready-made wrapper for library you are interested in, you shall do so :)
There were many attempts to make C#/C++ interop easier, but by far managed C++ from Microsoft is probably the best (though it is not part of C++ standard).
Another promising option is CXXI from Mono,
http://tirania.org/blog/archive/2011/Dec-19.html
which provides a standard compliant approach.
It still needs some hacking (Google Summer of Code 2012 maybe), but it should finally support Visual C++ and Windows.
Yes. You can instantiate and access a C++ class object directly from your own C# code via PInvoke, but it is very complicated and involves a lot of work, please go here and read what that C++ PInvoke Interop SDK can do.
http://www.xinterop.com/index.php/2013/04/13/introduction-to-c-pinvoke-interop-sdk/
(It is a commercial software though. I am the author)

.net wrapper for native dll - how to minimize risk of run-time error?

I am developing a C# application. Since I have some algorithms for least-squares fit in C/C++ that would be too cumbersome too translate, I have made the C++ code into a dll and then created a wrapper in C#.
In the C# code, I have defined a struct that is passed to the unmanaged C++ code as a pointer. The struct contains the initial guesstimates for the fitting functions, and it is also used to return the results of the fit.
It appears to me that you must define the struct in both the managed and the unmanaged code. However, someone using my source code in in the future might decide to change the fields of the struct in the C# application, without understanding that they also have to change the struct in the native code. This will result in a run-time error at best (and produce erroneous results at worse), but there will be no error message telling the developer / end user what is wrong.
From my understanding, it impossible to create a test in the unmanaged C++ DLL that checks if the struct contains the correct fields, but is it posible to have the DLL returning a struct of the correct format to the C# wrapper?
Otherwise, what ways are there to reduce the risk that some careless programmer in the future causes run-time errors that are hard to detect?
Sample code:
//C++
struct InputOutputStruct {
double a,b,c;
}
extern "C" __declspec(dllexport) void DoSomethingToStruct(InputOutputStruct* s)
{
// ... algorithm
}
//C#
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct InputOutputStruct {
public double a,b,c;
}
[DllImport("CpluplusDll.dll")]
public static unsafe extern bool DoSomethingToStruct(InputOutputStruct* s);
class CSharpWrapper {
static void Main(string[] args)
{
InputOutputStruct s = new InputOutputStruct();
unsafe {
InputOutpustruct* sPtr = &s;
DoSomethingToStruct(sPtr);
s = *sPtr;
}
}
}
It appears to me that you must define the struct in both the managed
and the unmanaged code.
Not true. This is what C++/CLI was invented for- facilitate much easier interoperation with C++ and .NET.
but is it posible to have the DLL returning a struct of the correct format to the C# wrapper?
I don't think so, because you always need to define the structs on the C# side.
Here are a solution which may work ( never tested ):
Give each struct which is shared a unique identifier on both sides ( GUID, Macros )
Create a reflection for C++ which contains informations about the the types which are used on C# and C++ side. This could be done by using macros.
Compare the C++ structs and the C# structs on startup by using the GUIDs, reflection and macros. You can also use sizeof to compare sizes first.
That could be a lot of work
When working on C++ side you still can make a lot of things wrong when you not know about the macros

declspec and stdcall vs declspec only

I'm a new person to C++ dll import topic and may be my question is very easy but I can not find it on google.
I have a very simple C++ win32 dll:
#include <iostream>
using namespace std;
extern "C"
{
__declspec(dllexport) void __stdcall DisplayHellowFromDLL()
{
cout<<"Hi"<<endl;
}
}
When I call this method from C# I do not have any problem, here is C# code
namespace UnmanagedTester
{
class Program
{
[DllImport(#"C:\CGlobalDll")]
public static extern void DisplayHellowFromDLL();
static void Main(string[] args)
{
Console.WriteLine("This is C# program");
DisplayHellowFromDLL();
}
}
}
As I expected the output is: "This is C# program" "Hi".
Now if I change the declaration of C function as:
__declspec(dllexport) void DisplayHellowFromDLL()
without __stdcall, I do not have any problem as well, and the question is:
When do I really need __declspec(dllexport) TYPE __stdcall and when I can use only __declspec(dllexport) TYPE ?
Thanks a lot.
You can think of it like this:
__declspec(dllexport) declares your function as a public function that your DLL exports;
__stdcall is a rather low-level detail that refers to the "calling convention" adopted by that function; specifically, __stdcall means that the callee cleans the stack;
alternative to __stdcall is __cdecl, which means: the caller cleans the stack.
__cdecl is the "natural" C calling convention; it supports the definition of vararg functions (like printf).
__stdcall is the default calling convention for DLL functions, so you don't need specify it if you are only going to call those functions through their DLL API.
This should explain what you are observing.
It works by accident because the function doesn't take any arguments. As soon as you do this on a function that does take arguments you'll start running out of luck. The call will leave the stack imbalanced, very unhealthy. You'd get the pInvokeStackImbalance MDA warning when you debug. An imbalanced stack can otherwise go unnoticed for a while, it tends to crash your program in the Release build.
You need to specify the calling convention if you compile the calling code with some other convention. Otherwise the default will work.
Ilya, you can also set the default calling convention in Project Properties -> Configuration Properties -> C/C++ -> Advanced -> Calling Convention.
If the default calling convention in your project is already set to __stdcall (/Gz), then adding __std

C++/CLI wrapper for C dll

So I have this C .dll source code which I want to use in my C# application. Instead of doing bunch of DllImports I've decided to write a wrapper for it in C++/CLI.
My C function takes a pointer to a struct with 4 callback functions in it:
typedef struct
{
PFN_IN readFp;
PFN_OUT writeFp;
}OPEN_ARGS;
C++/CLI shares the same .h file, therefore uses the same typedef.
C# code has it's own definition of this structure and delegates for CBs, because I can't attach .h to C# project.
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate Int32 PFN_OUT(IntPtr arg, IntPtr pSrc, Int32 len);
[StructLayout(LayoutKind.Sequential)]
public struct OPEN_ARGS
{
public PFN_IN readFp;
public PFN_OUT writeFp;
};
So, when I add my C++/CLI dll explicitly to C# project references, the compliler wouldn't accept calls to C++/CLI functions saying
"Error 2 Argument 2: cannot convert from 'WrapperTest.Program.OPEN_ARGS' to 'SAR_OPEN_ARGS'"
But if I include the C++/CLI dll implicitly like that
[DllImport("Wrapper.dll", CharSet = CharSet.Auto, EntryPoint = "?CLIOpen##YAHHUOPEN_ARGS###Z")]
public static extern int CLIOpen(int a, OPEN_ARGS args);
It will work just fine.
So is there a way to tell C# compiler to ignore this type cast error, or may be other way to wrap C code functions?
EDIT: cleaned up variable names for better readabiltiy
What if you did this another way. Since you have a C++/CLI DLL handling interop duties between the C DLL and the C# assembly, you could expose an equivalent API, only using more .NET-like concepts.
For example, instead of exposing the struct with function pointers, you could expose a class that has three events. The C# assembly would add handlers for those events. Inside the C++ DLL, it would use the function pointers that the C DLL expects, but their implementation would fire the .NET events that the C# assembly is handling.
This would provide a much better experience using the DLL on the C# side, and likely get rid of the interop compiler errors that you're encountering.
Please consider using SWIG to generate the wrapper code for all your pinvoke.
http://www.swig.org/Doc1.3/CSharp.html
So for managed C++, you can use the #pragma managed/unmanaged compiler directives instead of pInvoke, which it looks like you are using. Then you can compile managed and native code together into the same assembly, even the same CPP file.
Then you could do something like:
#pragma managed
// include your native headers here
#include "foo.h" // whatever you call it.
#using <System.dll> // what ever else you need here...
// Have to wrap a function in a class, since .NET doesn't allow free standing functions.
public ref class foo
{
public static int sarCLIOpen(int a, SARWrapperTest::Program::SAR_OPEN_ARGS args)
{
// do something to convert your managed args to native args.
::SAR_OPEN_ARGS native_args = ...
// then call your native function
return sarCLIOpen(a, native_args );
}
};

Categories

Resources