Is it possible to call a C function from C#.Net - c

I have a C lib and want to call function in this library from C# application. I tried creating a C++/CLI wrapper on the C lib by adding the C lib file as linker input and adding the source files as additional dependencies.
Is there any better way to achieve this as am not sure how to add C output to c# application.
My C Code -
__declspec(dllexport) unsigned long ConnectSession(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen);
My CPP Wrapper -
long MyClass::ConnectSessionWrapper(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen)
{
return ConnectSession(handle, publicKey, publicKeyLen);
}

The example will be, for Linux:
1) Create a C file, libtest.c with this content:
#include <stdio.h>
void print(const char *message)
{
printf("%s\\n", message);
}
That’s a simple pseudo-wrapper for printf. But represents any C function in the library you want to call. If you have a C++ function don’t forget to put extern C to avoid mangling the name.
2) create the C# file
using System;
using System.Runtime.InteropServices;
public class Tester
{
[DllImport("libtest.so", EntryPoint="print")]
static extern void print(string message);
public static void Main(string[] args)
{
print("Hello World C# => C++");
}
}
3) Unless you have the library libtest.so in a standard library path like “/usr/lib”, you are likely to see a System.DllNotFoundException, to fix this you can move your libtest.so to /usr/lib, or better yet, just add your CWD to the library path: export LD_LIBRARY_PATH=pwd
credits from here
EDIT
For Windows, it's not much different.
Taking an example from here, you only have yo enclose in your *.cpp file your method with extern "C"
Something like
extern "C"
{
//Note: must use __declspec(dllexport) to make (export) methods as 'public'
__declspec(dllexport) void DoSomethingInC(unsigned short int ExampleParam, unsigned char AnotherExampleParam)
{
printf("You called method DoSomethingInC(), You passed in %d and %c\n\r", ExampleParam, AnotherExampleParam);
}
}//End 'extern "C"' to prevent name mangling
then, compile, and in your C# file do
[DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")]
public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam);
and then just use it:
using System;
using System.Runtime.InteropServices;
public class Tester
{
[DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")]
public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam);
public static void Main(string[] args)
{
ushort var1 = 2;
char var2 = '';
DoSomethingInC(var1, var2);
}
}

UPDATE - Feb 22 2019: Since this answer has been getting quite a few upvotes, I decided to update it with a better way of calling the C method. Previously I had suggested using unsafe code, but the safe and correct way is to use MarshalAs attribute for converting a .NET string to a char*. Also, in VS2017 there is no Win32 project anymore, you'll probably have to create a Visual C++ dll or empty project and modify that. Thank you!
You can directly call C functions from C# by using P/Invoke.
Here's a short how-to on creating a C# lbrary that wraps around a C dll.
Create a new C# Library project (I'll call it "Wrapper")
Add a Win32 project to the solution, set application type to: DLL (I'll call it "CLibrary")
You can remove all the other cpp/h files since we won't need them
Rename the CLibrary.cpp file to CLibrary.c
Add a CLibrary.h header file
Now we need to configure the CLibrary project, right-click it and go to properties, and select Configuration: "All Configurations"
In Configuration Properties > C/C++ > Precompiled headers, set Precompiled Headers to: "Not using Precompiled Headers"
In the same C/C++ branch, go to Advanced, change Compile As to: "Compile as C code (/TC)"
Now in the Linker branch, go to General, and change Output File to: "$(SolutionDir)Wrapper\$(ProjectName).dll", this will copy the built C DLL to the C# project root.
CLibrary.h
__declspec(dllexport) unsigned long ConnectSession(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen);
CLibrary.c
#include "CLibrary.h"
unsigned long ConnectSession(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen)
{
return 42;
}
Right-click CLibrary project, build it, so we get the DLL in the C# project directory
Right-click C# Wrapper project, add existing item, add CLibrary.dll
Click on CLibrary.dll, go to the properties pane, set "Copy to output Directory" to "Copy Always"
It's a good idea to make the Wrapper project dependent on CLibrary so CLibrary gets built first, you can do that by right-clicking the Wrapper project, going to "Project Dependencies" and checking "CLibrary".
Now for the actual wrapper code:
ConnectSessionWrapper.cs
using System.Runtime.InteropServices;
namespace Wrapper
{
public class ConnectSessionWrapper
{
[DllImport("CLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
static extern uint ConnectSession(uint handle,
[MarshalAs(UnmanagedType.LPStr)] string publicKey,
char publicKeyLen);
public uint GetConnectSession(uint handle,
string publicKey,
char publicKeyLen)
{
return ConnectSession(handle, publicKey, publicKeyLen);
}
}
}
Now just call GetConnectSession, and it should return 42.
Result:

Okay well, Open VS 2010, Goto File -> New -> Project -> Visual C++ -> Win32 -> Win32 Project and give it a name (HelloWorldDll in my case), Then in the window that follows under Application Type choose 'DLL' and under Additonal Options choose 'Empty Project'.
Now goto your Solution Explorer tab usually right hand side of VS window, right click Source Files -> Add Item -> C++ file (.cpp) and give it a name (HelloWorld in my case)
Then in the new class paste this code:
#include <stdio.h>
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL()
{
printf ("Hello from DLL !\n");
}
}
Now Build the project, after navigate to your projects DEBUG folder and there you should find: HelloWorldDll.dll.
Now, lets create our C# app which will access the dll, Goto File -> New -> Project -> Visual C# -> Console Application and give it a name (CallDllCSharp), now copy and paste this code to your main:
using System;
using System.Runtime.InteropServices;
...
static void Main(string[] args)
{
Console.WriteLine("This is C# program");
DisplayHelloFromDLL();
Console.ReadKey();
}
and build the program, now that we have both our apps built lets use them, get your *.dll and your .exe (bin/debug/.exe) in the same directory, and execute the application output should be
This is C# program
Hello from DLL !
Hope that clears some of your issues up.
References:
How to create a DLL library in C and then use it with C#

NOTE : BELOW CODE IS FOR MULTIPLE METHODS FROM DLL.
[DllImport("MyLibc.so")] public static extern bool MyLib_GetName();
[DllImport("MyLibc.so")] public static extern bool MyLib_SetName(string name);
[DllImport("MyLibc.so")] public static extern bool MyLib_DisplayName(string name);
public static void Main(string[] args)
{
string name = MyLib_GetName();
MyLib_SetName(name);
MyLib_DisplayName(name);
}

The P/Invoke method has been described extensively and repeatedly, ok so far.
What I'm missing here is, that the C++/CLI method has a big advantage: Calling safety.
In contrast to P/Invoke, where the call of the C funtion is like shooting blind into the sky (if this comparison is allowed), nobody will check the function arguments when calling the C function.
Using C++/CLI in this case means normally, you include a headerfile with the functions prototypes you want to use. If you are calling the C function with wrong/to much /to few arguments, the compiler will tell you.
I don't think you can say in general which is the better method, honestly I don't like either of them.

Related

DLL dependency to static library

I currently build a purely static library MainLib for our customers that contains all symbols so that they can intrgrate it into their program. For several reasons, I now need to deliver a DLL version of MainLib that contains parts of the symbols alongside a static library FeatureLib that contains the remaining symbols. One reason is that we want to avoid bad guys using our software by simply stealing the DLL that is provided via the program of our customer. This wouldn't work if parts of the symbols are integrated within the calling software via a static library. The user of the package shall only be able to use the DLL if he added the symbols of FeatureLib into his application.
For Linux, I can make this work like a charm,i.e. the symbol doFeature() is not within libMainLib.so, but I don't succeed on this for Windows.
CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project(MainLib)
add_library(FeatureLib STATIC src/FeatureLib.c)
target_include_directories(FeatureLib PUBLIC include
PRIVATE src)
add_library(MainLib SHARED src/MainLib.c)
target_include_directories(MainLib PUBLIC include
PRIVATE src)
# I don't want to include symbols from FeatureLib into shared MainLib
#target_link_libraries(MainLib PRIVATE FeatureLib)
add_executable(MainLibDemo src/demo.c)
target_link_libraries(MainLibDemo MainLib FeatureLib) #resolve symbol doFeature()
FeatureLib.h:
extern int doFeature(int input);
MainLib.h:
extern __declspec(dllexport) int MainLib(int input);
FeatureLib.c:
#include "FeatureLib.h"
int doFeature(int input) {return 4;}
MainLib.c:
#include "FeatureLib.h"
#include "MainLib.h"
__declspec(dllexport) int MainLib(int input)
{
if (input > 2) {
return doFeature(input);
} else {
return doFeature(0);
}
}
demo.c:
#include <stdio.h>
#include <stdlib.h>
#include "MainLib.h"
int main(int argc, char **argv)
{
if(argc > 1)
return MainLib(atoi(argv[1]));
else
return 0;
}
With this, I get the following compilation error:
"C:\Daten\tmp\DemoProject\simple\build\ALL_BUILD.vcxproj" (Standardziel) (1) ->
"C:\Daten\tmp\DemoProject\simple\build\MainLib.vcxproj" (Standardziel) (4) ->
(Link Ziel) ->
MainLib.obj : error LNK2019: unresolved external symbol _doFeature referenced in function _MainLib [C:\Daten\tmp\DemoProject\simple\build\MainLib.vcxproj]
C:\Daten\tmp\DemoProject\simple\build\Debug\MainLib.dll : fatal error LNK1120: 1 unresolved externals [C:\Daten\tmp\DemoProject\simple\build\MainLib.vcxproj]
0 Warnung(en)
2 Fehler
Is this even possible with Windows? What do I have to do to make it work and how can I verify it other than not linking FeatureLib to MainLibDemo. Any ideas are very welcome.
Kind regards,
Florian
The way you do it under Linux will not work under Windows
because dynamic linking works differently here.
Here is one strategy that could work.
In MainLib.dll code, instead of directly calling doFeature
you need to define a global pointer variable of proper function
pointer type and use it to call the function.
This will allow to build MainLib.dll without errors.
Now you need to set this pointer variable. One way would be:
Add exported function to MainLib.dll that takes pointers
to all functions that the DLL needs from the executable.
In FeatureLib.lib code add an initialisation function
that the application will need to call before using
your DLL which will pass pointers to its peers to the DLL.
This is basically the way most programs with plugins use to
give the plugins access to their facilities.
Another way would be to (Warning! I have not tested this specific
solution):
Declare the functions in FeatureLib.lib as exported
with __declspec(dllexport). This way they will be exported
from executable.
In MainLib.dll before first using the pointers use
GetModuleHandle and GetProcAddress to obtain the pointers.
It would best be done in some initialisation function for the
library. Otherwise you need to take care to avoid race conditions.
Hope this will help.
Though I do not think your copy protection scheme will work.
Andrew Henle is right in his comment: it is not hard
to extract the needed code from one executable and include it
in another.

deploy app with dll wrapper

I'm trying to deploy a WinForms application that involves importing an external DLL with a wrapper class, like this:
[DllImport(ImportedDllName, CallingConvention=CallingConvention.StdCall, CharSet = CharSet.Unicode)]
private static extern void cfg_put_MixerFilePlayerEnabled(IntPtr cfgPtr, int Enabled);
[DllImport(ImportedDllName, CallingConvention=CallingConvention.StdCall, CharSet = CharSet.Unicode)]
private static extern void cfg_get_MixerFilePlayerEnabled(IntPtr cfgPtr, ref int Enabled);
public int MixerFilePlayerEnabled
{
get { int s = 0; cfg_get_MixerFilePlayerEnabled(m_cfgPtr, ref s); return s; }
set { cfg_put_MixerFilePlayerEnabled(m_cfgPtr, value); }
}
So, when I run my application debbugin, all work right, but when I publish it, I receive a DLL not found exception.
How can I solve this issue?
If your debug machine and publish machine are the same PC:
Find out "the external DLL" is x86 or x64. Your C# wrapper should also run as x86 or x64 correspondingly.
Use dependencywalker to make sure you C# wrapper can find the "the external DLL".
Write a cpp exe demo to make sure cpp exe can use that dll. Then try C# wrapper.
If your debug machine and publish machine are two PCs:
Install the right version of vcredist of "the external DLL".
Use dependencywalker to find out what dll you missed.
Write a cpp exe demo to make sure cpp exe can use that dll. Then try C# wrapper.

Mocking C functions in MSVC (Visual Studio)

I am reading several articles on mocking C functions (like CMock, or CMocka), but I am not sure how the actual functions are replaced with mocked functions in this process. For example, CMocka relies on automatic wrapping using a GNU compiler, which supports parameters like --wrap to append the __wrap prefix to function calls, or weak symbols which allow you to override any symbol you like.
But how do you do this in Visual Studio, for pretty much all other frameworks?
For example, CMock has an example similar to this (simplified a lot here):
// myfunc.c
#include <parsestuff.h>
// this is the function we would like to test
int MyFunc(char* Command)
{
// this is the call to the function we will mock
return ParseStuff(Command);
}
There is also the actual implementation, which contains the actual function the linker should find in the actual application:
// parsestuff.c
int ParseStuff(char* cmd)
{
// do some actual work
return 42;
}
Now, during testing the Ruby script creates mock functions like:
// MockParseStuff.c (auto created by cmock)
int ParseStuff(char* Cmd);
void ParseStuff_ExpectAndReturn(char* Cmd, int toReturn);
But if the VS project already includes parsestuff.c, how will it be possible that the call from myfunc.c ends up in MockParseStuff.c?
Does this mean I cannot have parsestuff.c included in the unit testing project? But if this is the case, then it's also impossible to mock, for example, MyFunc from myfunc.c in any tests, since I already had to include the file it in order to test it?
(Update) I am also aware that I can include the .c file instead of the .h file, and then do some preprocessor stuff to replace the original call, like:
// replace ParseStuff with ParseStuff_wrap
#define ParseStuff ParseStuff_wrap
// include the source instead of the header
#include <myfunc.c>
#undef ParseStuff
int ParseStuff_wrap(char* cmd)
{
// this will get called from MyFunc,
// which is now statically included
}
but this seems like a lot of plumbing, and I don't even see it mentioned anywhere.
Here's a simple and short solution with hippomocks:
I created an empty Win32 console application with
main.cpp
myfunc.c + myfunc.h
parsestuff.c, parsestuff.h
and added the code from your example.
With help of hippomocks, you can mock every C-Function. Here's how my main.cpp looks like:
#include "stdafx.h"
#include "myfunc.h"
#include "hippomocks.h"
extern "C" int ParseStuff(char* cmd);
int _tmain(int argc, _TCHAR* argv[])
{
MockRepository mocks;
mocks.ExpectCallFunc(ParseStuff).Return(4711);
char buf[10] = "";
int result = MyFunc(buf);
return result; //assert result is 4711
}
HippoMocks is a free, simple and very powerful one-header framework and can be downloaded on GitHub.
Hope I've earned the bounty :)
UPDATE, How it works:
HippoMocks gets the func pointer to ParseStuff
HippoMocks builds a replacement func pointer to a template function with same signature and own implementation.
Hippomocks patches the jmp opcode from the function call prologue in memory, so that it points to the replaced function.
Replacement and memory patch are released after call or in destructor.
Here's how it looks like on my machine:
#ILT+3080(_ParseStuff):
00D21C0D jmp HippoMocks::mockFuncs<char,int>::static_expectation1<0,char *> (0D21DB1h)
If you watch the memory address 00D21C0D (may differ from run to run) in memory window, you will see, that it gets patched after the call of ExpectCallFunc.
I have not dealt with the C mocking libraries or Visual Studio, but I have thought about this in my own project. The Feathers book suggests the preprocessor seam or the link seam as a tool for dealing with this. You already mentioned the preprocessor seam, so I'll focus on the link seam.
The link seam requires the mocked function to be in a library, and the mock function to be in a library. The test can link against the mock function library while the target application can link against the original library.
Of course, as you mention, to mock MyFunc() you will have to create another library and a separate test application to link against it (or dynamically load and unload libraries in the test application).
It sounds quite laborious which is why I am procrastinating adding tests in my own application!
Hope this helps!

suppress or intercept CRT checks from instances of CRT from other dlls

My program loads several dlls and calls their functions. The dlls can use different versions of CRT.
When C runtime checks the validity of arguments and finds problems, it calls the invalid parameter handle, which in turn, closes the application, with or without the "Send-Don't send" dialog.
I tried calling *_set_invalid_parameter_handler* but it only works if it is called from within the bad dll. I tried SetErrorMode, but all I managed to do is get the process killed without the dialog.
Is there any way to handle those exceptions? I don't care if some resources are compromised. All I want is to allow users to save the configuration. If the dialog appears, they click on it and kill the process.
EDIT
It turns out the solution to load all versions of CRT or to enumerate all DLLs fails. To make all clear, here is a small example to play with:
This would be my main application (let's call the file application.c):
#include <windows.h>
void myInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) {
wprintf(L"Invalid parameter detected in function %s. File: %s Line: %d\n", function, file, line);
wprintf(L"Expression: %s\n", expression);
}
void fixMyProblem() {
}
int main(int argc, char **argv) {
HMODULE hModule = LoadLibrary("extension.dll");
void (WINAPI *function)() = GetProcAddress(hModule, "function");
fixMyProblem();
function();
}
This application loads a dll that does bad things (it is not developed by me, so I will not accept any solution telling me to fix the bugs there). Lets' call that file extension.c.
#include <stdio.h>
__declspec(dllexport) void function() {
printf("do bad stuff");
fopen(NULL, "r");
}
To compile, do:
cl extension.c /link /OUT:extension.dll /DLL
cl application.c
The question is what do I do in function fixMyProblem(), so that I don't get the send/don't send dialog on XP or the application has stopped working dialog on 7.
According to David Gladfelter I should do
void fixMyProblem() {
_set_invalid_parameter_handler(myInvalidParameterHandler);
}
and also do this for each version CRT available. It turns out that even with one single version of CRT (I use the same for both exe and dll), it still does not work. They both use the same version of CRT, but is seems they do not use the same CRT.
If this is is the case, I assume that the stuff I have to change is inside the DLL. Of course, it does not export *_set_invalid_parameter_handler*.
But to be fair to David Heffernan, here is the implementation for his solution:
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")
void fixMyProblem() {
HANDLE hProcess = GetCurrentProcess();
HMODULE *hModules;
DWORD requiredSize = 0;
DWORD secondRequiredSize = 0;
if (!EnumProcessModules(hProcess, NULL, 0, &requiredSize)) {
printf("oops\n");
return;
}
hModules = malloc(requiredSize);
if (EnumProcessModules(hProcess, hModules, requiredSize, &secondRequiredSize)) {
int i;
int loadedModules = min(requiredSize, secondRequiredSize) / sizeof(HMODULE);
for (i = 0; i < loadedModules; i++) {
void *(WINAPI *_set_invalid_parameter_handler_function)(void *) = (void *(WINAPI *)(void *)) GetProcAddress(hModules[i], "_set_invalid_parameter_handler");
if (_set_invalid_parameter_handler_function != NULL) {
_set_invalid_parameter_handler_function(myInvalidParameterHandler);
printf("fixed dll %d\n", i);
}
}
} else {
printf("oops\n");
}
free(hModules);
}
For my real application, not this test, I get 1 dll fixed (msvcp90.dll). It still does not fix my problem.
I would appreciate any help in solving this.
If the dll is built with a statically linked CRT, then the state and functions of the CRT will be local to that instance of the dll.
I am assuming the invalid parameter handler used by the CRT is calling the UnhandledExceptionFilter function, from the OS, to show that "nice" error dialog.
You could try to hook functions like UnhandledExceptionFilter or TerminateProcess, making the dll use your own functions instead. You can do this by parsing the Import Address Table of the loaded dll, search for the function name you are interested, and change the address to point to your function.
You could always enumerate the modules in your process and if it's a C runtime then get hold of the invalid parameter handler with a call to GetProcAddress.
But you'd be better off trying to fix the bugs at root. Trying to ignore such problems mostly just leads to further problems because memory gets corrupted and so on.
You could create another DLL that uses the same version of the CRT as the version used by the DLL that causes the invalid parameter handler to be called and register the invalid parameter handler it in that new DLL. The invalid parameter handler is global to the process/CRT-version combination.
If you don't know what version the DLL is using and you can't figure it out, worst-case is you create several DLL's, one for each CRT version:
VS 6 static/dynamic/multithreaded/single-threaded
VS.NET static/dynamic/multithreaded/single-threaded
VS 2003 static/dynamic/multithreaded/single-threaded
VS 2005 static/dynamic
VS 2008 static/dynamic
VS 2010 static/dynamic
You could probably create them as static .lib files and link them all into one (very confused) DLL.

Vala vapi files documentation

I'd like to hack on an existing GLib based C project using Vala.
Basically what I'm doing is, at the beginning of my build process, using valac to generate .c and .h files from my .vala files and then just compiling the generated files the way I would any .c or .h file.
This is probably not the best way, but seems to be working alright for the most part.
My problem is that I'm having a hard time accessing my existing C code from my Vala code. Is there an easy way to do this?
I've tried writing my own .vapi files (I didn't have any luck with the tool that came with vala), but I can't find any decent documentation on how to write these.
Does any exist? Do I need one of these files to call existing C code?
Yes, to call a C function, you need to write a binding for it. The process is described in http://live.gnome.org/Vala/Tutorial#Binding_Libraries_with_VAPI_Files, however, this doesn't apply directly to custom functions or libraries written without GObject. You'll probably need help from #vala IRC channel if you have complex binding for non-GObject libraries.
However, most of the time, we use simple vapi files to bind some autoconf define or some functions written in plain C, for efficiency reason or broken vala, or whatever other reason. And this is the way that most people do:
myfunc.vapi
[CCode (cheader_filename = "myfunc.h")]
namespace MyFunc {
[CCode (cname = "my_func_foo")]
public string foo (int bar, Object? o = null);
}
myfunc.h (and corresponding implementation in a .c linked with your project)
#include <glib-object.h>
char* my_func_foo(int bar, GObject* o)
example.vala could be
using MyFunc;
void main() {
baz = foo(42);
}
When compiling with valac, use --vapidir= to give the directory location of the myfunc.vapi. Depending on your build system, you may need to pass extra argument to valac or gcc CFLAGS in order to link everything together.
The only addition I would make to elmarco's answer is the extern keyword. If you're trying to access a single C function that's already available in one of your packages or the standard C/Posix libraries, you can access it easily this way.
For GLib-based libraries written in C you can try to generate gir-files from your C-sources: Vala/Bindings.
Doing it manually is no problem too. Suppose you have a library which defines SomelibClass1 in C with a method called do_something which takes a string.
The name of the headerfile is "somelib.h". Then the corresponding vapi is as simple as the following:
somelib.vapi:
[CCode (cheader_filename="somelib.h")]
namespace Somelib {
public class Class1 {
public void do_something (string str);
}
}
Documentation for writing vapis for non-GLib libraries can be found here: Vala/LegacyBindings
This is actually really easy. Lets take an excerpt from posix.vapi:
[Compact]
[CCode (cname = "FILE", free_function = "fclose", cheader_filename = "stdio.h")]
public class FILE {
[CCode (cname = "fopen")]
public static FILE? open (string path, string mode);
[CCode (cname = "fgets", instance_pos = -1)]
public unowned string? gets (char[] s);
}
This implements the following C-Function:
FILE *fopen (const char *path, const char *mode);
char *fgets (char *s, int size, FILE *stream);
When discarding the instance_pos attribute vala assumes that the object is the first parameter to a method. This way it is possible to bind c-constructs that are roughly object-oriented. The free_method of the compact-class is called when the object is dereferenced.
The CCode(cname)-attribute of a method, class, struct, etc. has to be the name of it as it would be in C.
There is a lot more to this subject, but this should give you a general overview.
It would probably be easier to just access your vala code from c. As all you have to do is just compile to C.

Resources