vsnprintf and snprintf causing dll to not load - c#

I've been fighting this for days. I have a Visual Studio .net project written in C# that needs to load a dll written in C using gcc compilers on the Codeblocks IDE.
The dll can be loaded and used fine, but when I use vsnprintf in the dll, the .net project says "Unable to load DLL. The specified module could not be found." whenever I try to call a function from the dll.
Relevant C# code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace Scratchpad
{
public partial class frmMain : Form
{
[DllImport("testpielibs", CallingConvention = CallingConvention.Cdecl)]
static extern void SomeFunction(string a);
private void button3_Click(object sender, EventArgs e)
{
SomeFunction("ABC");
}
}
}
Relevant C (the DLL) code:
#include <stdio.h>
#include <stdarg.h>
#define DLL_EXPORT __declspec(dllexport)
void DLL_EXPORT SomeFunction(const LPCSTR sometext)
{
MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION);
}
DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
int log_printf(char *format, ...)
{
char msg[256];
va_list ap;
memset(msg, 0, sizeof msg);
va_start(ap, format);
vsnprintf(msg, 256, format, ap);
va_end(ap);
return 0;
}
Notice that "SomeFunction" doesn't even call "log_printf". The project builds fine regardless, and when I comment out the line with vsnprintf it works like it should with the .net project, but that one line is what's causing the dll to be unable to load in the .net project.
Incase this is releveant, here are my linker libraries for the dll:
ws2_32
iphlpapi
mswsock
winmm
user32
Also, I feel like it might be important to note that the other day, just before all of this happened, I got an error from codeblocks saying something about my config file being corrupted. This project was building fine before then, but I had to go back and manually re-assign the compiler and linker settings.
Any suggestions?
UPDATE: snprintf is causing the same issue. I can use sprintf and vsprintf, but snprintf and vsnprintf are causing the dll to not be loaded in the C# project, even though the dll will still build with no errors or warnings. I've looked into the calling conventions used to import my dll functions into my c# project, and Cdecl seems like the way to go since it specifically says that it "enables calling functions with varargs, which makes it appropriate to use for methods that accept a variable number of parameters, such as Printf." I've also tried importing SomeFunction using calling conventions Winapi, StdCall and ThisCall, but they all have the same results. Any help would be really appreciated, I have been stumped on this for a while.

Related

Access a function present in C# dll using Python

I want to access a function my_function() present in a c# file which is compiled into a .net dll - abc.dll.
C# file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
public class Class1
{
public string my_function()
{
return "Hello World.. :-";
}
}
}
After compiling the above code to abc.dll
Using the below python trying to access my_function()
import ctypes
lib = ctypes.WinDLL('abc.dll')
print lib.my_function()
Above code throws error
lib.my_function()
Traceback (most recent call last):
File "", line 1, in
File "C:\Anaconda\lib\ctypes__init__.py", line 378, in getattr
func = self.getitem(name)
File "C:\Anaconda\lib\ctypes__init__.py", line 383, in getitem
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'my_function' not found
You haven't made the function visible in the DLL.
There are a few different ways you can do this. The easiest is probably to use the unmanagedexports package. It allows you to call C# functions directly like normal C functions by decorating your function with [DllExport] attribute, like P/Invoke's DllImport. It uses part of the subsystem meant to make C++/CLI mixed managed libraries work.
C# code
class Example
{
[DllExport("ExampleFunction", CallingConvention = CallingConvention.StdCall)]
public static int ExampleFunction(int a, int b)
{
return a + b;
}
}
Python
import ctypes
lib = ctypes.WinDLL('example.dll')
print lib.ExampleFunction(12, 34)

No functions in C# DLL with RGiesecke.DllExport

I am trying to make a DLL in C# for use in a couple other languages. I found RGiesecke's DllExport but it doesn't seem to work. It builds just fine and makes a dll, but when I open it in Dependency Walker it doesn't show any functions, and my calling code can't find them either.
I created a new "Class Library" project (VS 2013) and then installed "Unmanaged Exports (DllExport for .Net)" from NuGet. Are there any project settings I need?
Here is my code.
using System;
using System.Collections.Generic;
using System.Text;
using RGiesecke.DllExport;
namespace ToolServiceDLL
{
public class Class1
{
[DllExport("addUp", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
public static double addUp(double num1, double num2)
{
return num1 + num2;
}
[DllExport("get5", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
public static int get5()
{
return 5;
}
}
}
I found the problem. It has it in the RGiesecke Documentation, but I missed it. In the project settings->Build->Platform target: you can not have it set to "Any CPU". You must have it set to x64 or x86 depending on if you want to use it in a a 64 or 32 bit application.
I had a similar problem, but had already set the platform target to x64 and had the following error:
The name 'CallingConvention' does not exist in the current context
I found adding the using directive System.Runtime.InteropServices resolve the problem.
This is a good question and worked for me. Just took a bit more time than it should due to the Python side where I made a mistake. Here is the working code in Python3
import sys
import clr
sys.path.insert(0,'C:\\your_path\\Py2NetComm\\bin\\Debug')
clr.AddReference("Py2NetComm")
import ToolServiceDLL as p2n
ret = p2n.Class1.addUp(2,3)
print("addUp:", ret)

Unity3D call external dll

I am trying to build a native plugin for Unity3D Pro (5.0). So far, I have built a DLL file in VS express 2013 for Windows, I have created a sample Unity project just for that and linked the library, but I am still getting an error and I cannot seem to move. Google wasn't very helpful in that matter ...
I am trying to add a DLL with my own low-level stuff for Windows Store target.
The stuff I am trying to access this way doesn't matter, I am stuck at hello world example app.
Visual Studio project
Dll3.cpp
#include "pch.h"
#include "Dll3.h"
extern "C" __declspec(dllexport) int testFunc(int a, int b) {
return a + b;
}
Dll3.h
#pragma once
using namespace std;
extern "C" __declspec(dllexport) int testFunc(int a, int b);
dllmain.cpp
#include "pch.h"
BOOL APIENTRY DllMain(HMODULE /* 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;
}
pch.h
#pragma once
#include "targetver.h"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#endif
// Windows Header Files:
#include <windows.h>
pch.cpp
#include "pch.h"
and I set the build target to x64, the DLL file exported successfully without any errors or warnings.
Unity Project
I plopped the Dll3.dll file to the Assets/ folder. At first, I had it in Assets/Plugins/ but I figured out it didn't matter at all.
test.cs
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class test : MonoBehaviour {
// Dll import according to Unity Manual
#if UNITY_IPHONE || UNITY_XBOX360
[DllImport ("__Internal")]
#else
[DllImport ("Dll3")]
#endif
private static extern int testFunc (int a, int b);
// Use this for initialization
void Start () {
int a = 1;
int b = 2;
int c = testFunc (a, b);
Debug.Log (c.ToString ());
}
// Update is called once per frame
void Update () {
}
}
Then I created an empty game object, assigned this script to it, compiled and run. It compiled without any errors or warnings, but when running (in Editor), I got this:
Failed to load 'Assets/Dll3.dll' with error 'This operation is only valid in the context of an app container.', GetDllDirectory returned ''. If GetDllDirectory returned non empty path, check that you're using SetDirectoryDll correctly.
Failed to load 'Assets/Dll3.dll' with error 'This operation is only valid in the context of an app container.', GetDllDirectory returned ''. If GetDllDirectory returned non empty path, check that you're using SetDirectoryDll correctly.
DllNotFoundException: Assets/Dll3.dll
test.Start () (at Assets/test.cs:18)
Can anyone, please point me to where I am doing the mistake? I am used to Unix (OSX/Linux) environment and Windows very non-standard for me. I do not understand completely the concept of the VS DLL project. I would be grateful for any help. Thank you
Yeah, it was correct from the start. I just needed to run it in Visual Studio Simulator, as a Store App on my desktop or deploy it to my development tablet PC. It does NOT run in the Unity Editor - I am such a fool :-)

Creating a CPP DLL for use in a C# program

So I have a WPF solution. I added a new project and added a CPP Dll project to it.
I used this example. Pretty straight forward.
http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w
Here is my code
CppTestDll.cpp
#include <stdio.h>
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL()
{
printf("Hello from DLL !\n");
}
}
When I build this I do in fact get a DLL
Now when I go into my WPF app and attempt to add a reference to this DLL I get this error.
"A reference to 'C:\DIR\testcppdll.dll' could not be added. Please
make sure that the file is accessible, and that it is a valid assembly
or COM component."
If you look in the example you cite:
Creating a simple C# application:
Start Visual Studio .NET. Go to File->New->Project.
Select Visual C#
Project. ... (you can select WPF Project)
Give the name to your application. Press OK. Into the specified
class, insert the following two lines:
[DllImport("TestLib.dll")]
public static extern void DisplayHelloFromDLL ();
In C#, keyword extern indicates that the method is implemented externally.
Your code should look something like this:
using System;
using System.Runtime.InteropServices; // DLL support
class HelloWorld
{
[DllImport("TestLib.dll")]
public static extern void DisplayHelloFromDLL ();
public void SomeFunction()
{
Console.WriteLine ("This is C# program");
DisplayHelloFromDLL ();
}
}
You don't add a reference to the to the DLL - you P/Invoke the Function using DLLImport

Passing argument to c# callback from c++

Below is my code in c#...
here callback is too implemented in c# only.
i want a callback from c++ dll
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
class Program
{
// [DllImport("C:/Users/kool/Documents/Visual Studio 2010/Projects/DLL/Debug/DLL.dll", CallingConvention = CallingConvention.Cdecl)]
static void Main(string[] args)
{
function1(function2); // i want thia function2 to be fetched from ++ dll
}
public delegate void fPointer(); // point to every functions that it has void as return value and with no input parameter
public static void function1(fPointer ftr)
{
fPointer point = new fPointer(ftr);
point();
}
public static void function2()
{
Console.WriteLine("Bla");
}
}
i will createa a dLL from where i will send function2 to
function1(function2);
how can i implement it??
One way is exporting the C# assembly as a type library and using it from C++ as if it were a COM component.
Use TlbExp.exe in the Visual Studio command prompt to export the C# assembly as a type library. Then register the type library with RegAsm.exe. Then in the C++ code use the #import directive to import the type library. You can now use the C# classes from C++ as if they were COM classes.
For more detail see: http://msdn.microsoft.com/en-us/library/ms172270.aspx
Edit: Sorry, which is it that you want to do: use C++ from C#, or use C# from C++?
Either one is possible. The link above explains how to use C# from C++. This one explains how to use C++ from C#: http://msdn.microsoft.com/en-us/library/z6tx9dw3.aspx
You can send pointer to your managed .net function and call it from unmamaged code (callback).
Detail here http://habrahabr.ru/post/130690/ (use google to translate it from russian if needed, but you need to look at last two code example).
Also check your code calling - it should comply on both managed and unmanaged sides (use __stdcall in C-code and CallingConvention = CallingConvention.Cdecl in DllImport attribute).

Categories