I have a dll for 32bit and 64bit and now I want that my exe call the dll from according to solution platform,means when x64 is set then the dll of 64bit will call.For this I declare a function GetPlatform().
Public Function GetPlateform() As String
Dim var1 As String
If (IntPtr.Size = 8) Then
var1 = hellox64
Else
var1 = hello
End If
Return var1
End Function
and when the form load
this var1 is assign to var and finally.
Public Declare Function function1 Lib "var" (ByVal Id As Integer) As Integer
But When I debug the code "DllNotFoundException" is ocuured.
NOTE:The dll is in vc++.
Store your native dlls into subfolders and hint the Library Loader by filling accordingly the PATH process environment variable with the path to the correct version to load.
For instance, given this tree layout...
Your_assembly.dll
|_NativeBinaries
|_x86
|_your_native.dll
|_amd64
|_your_native.dll
...and this code (sorry, C#, no VB.Net :-/ )...
internal static class NativeMethods
{
private const string nativeName = "your_native";
static NativeMethods()
{
string originalAssemblypath = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath;
string currentArchSubPath = "NativeBinaries/x86";
// Is this a 64 bits process?
if (IntPtr.Size == 8)
{
currentArchSubPath = "NativeBinaries/amd64";
}
string path = Path.Combine(Path.GetDirectoryName(originalAssemblypath), currentArchSubPath);
const string pathEnvVariable = "PATH";
Environment.SetEnvironmentVariable(pathEnvVariable,
String.Format("{0}{1}{2}", path, Path.PathSeparator, Environment.GetEnvironmentVariable(pathEnvVariable)));
}
[DllImport(nativeName)]
public static extern int function1(int param);
[DllImport(nativeName)]
public static extern int function2(int param);
}
...function1 and function2 would be dynamically bound to either the 32 or 64 bits version of the native code, depending on the size of an IntPtr (more on this in this post from Scott Hanselman or this StackOverflow question).
Note 1: This solution is especially useful when both versions of the dll bear the same name or if you're not willing to duplicate every extern references.
Note 2: This has already been successfully implemented in LibGit2Sharp.
No, you cannot dynamically create a reference to the DLL in a lib statement. However, you may (disclaimer: have not tried) be able to create two references and call the appropriate one in your code.
Public Declare Function Function132 Lib "My32BitLib.DLL" Alias "function1" (ByVal Id As Integer) As Integer
Public Declare Function Function164 Lib "My64BitLib.DLL" Alias "function1" (ByVal Id As Integer) As Integer
You will then need to branch on the platform and call the appropriate alias function name (Function132 or Function164) depending on the platform.
Related
I have below code snippet, which gets a pointer from a C API which is defined in a dll. Using marshalling I am trying to get the structure array, which is my requirement.
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
Public Class vb_menu_dotnet
Public level As Short
Public menu_id As String
End Class
Dim current As IntPtr
Dim outArray As IntPtr
Dim manArray(100) As vb_menu_dotnet
vb_dotnet_get_menu_hierarchy(p_menu_handle, p_apl_id, outArray) //C API call
current = outArray
Dim j As Integer
For j = 1 To 100
manArray(j) = New vb_menu_dotnet()
Marshal.PtrToStructure(current, manArray(j)) //Access Violation Exception
The prototype of C API is as below:
vb_dotnet_get_menu_hierarchy(tcodss_handle_t p_menu_handle,char* p_apl_id,vb_menu_dotnet** p_menu_array)
Structure defination :
typedef struct {
short level;
char* menu_id;
} vb_menu_dotnet;
The same code snippet works when both dll and above code is built with x86 option.
But when ran with x64 option i get AccessViolation Exception at,
Marshal.PtrToStructure(current, manArray(j))
Note: Using VS2010, framework 4.0, Windows 7 64 bit OS
I'm trying to invoke on dll method from an ASP.net web. It's working on a W2003 server but the same dll and the same web is crashing on w2008 server R2 with IIS 7.5.I'm doing like this to import the dll:
<DllImport("Cripto.dll")> _
Public Shared Function DesCipher(ByVal uiMode As Integer, ByVal uiLength As Integer, ByVal szSourceData As String) As String
End Function
I have tried a 64 bits dll compile but the problem remains.
I'm going mad...
Please Help!
Finally I have found the clue.
It is a memory location problem. The main function was returning an array like this:
char retorno[10000];
The function was declared in the dll code as "char*"
By changing these lines:
ULONG ulSize = strlen((char*)retorno) + sizeof(char);
char* pszReturn = NULL;
pszReturn = (char*)::GlobalAlloc(GMEM_FIXED, ulSize);
strcpy(pszReturn, (char*)retorno);
return pszReturn;
instead of
return ((char *)retorno)
Now it's working.
I'm attempting to call a method on the ssdeep fuzzy.dll
The .h file is here and a friendly reference is here
Specifically, I'm trying to call this method....
int fuzzy_hash_filename (
const char * filename,
char * result
)
I've got the following...
<DllImport("C:\SSDeep\Fuzzy.dll", EntryPoint:="fuzzy_hash_filename")>
Private Shared Function fuzzy_hash_filename(
<InAttribute(),
MarshalAsAttribute(UnmanagedType.LPStr)>
ByVal Filename As String, ByVal Result As StringBuilder) As Integer
End Function
Public Shared Function FuzzyHash(Filename As String) As String
Dim Ret As New StringBuilder
Ret.Capacity = NativeConstants.FUZZY_MAX_RESULT
Dim Success = fuzzy_hash_filename(Filename, Ret)
If Success <> 0 Then
Throw New Exception("SSDeep fuzzy hashing failed")
End If
Return Ret.ToString
End Function
If I run this code, VS gives me a modal dialogue
A call to PInvoke function '(Blah)::fuzzy_hash_filename' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
(FWIW The call seems to succeed if I ignore the warning so I must be close)
What change do I need to make to my definition to get this going?
I found someone that had the same issue on MSDN forums:
Concerning the PInvokeStackImbalance.
1.1 This is usually due to mismatch of the calling convention used by the API and that declared for the API in the C# code.
1.2 By default, if the CallingConvention argument for the DllImportAttribute is not set, then StdCall is used by default.
1.3 If the DoSomething() API is to use __cdecl (as is the default in C++ projects), then you should use the following declaration for
DoSomething() in the C# code : [DllImport(#"dll.dll",
CallingConvention=CallingConvention.Cdecl)]
1.4 Also, I suggest that you declare the API as extern "C" otherwise it will be subject to name mangling by the C++ compiler.
The accepted answer appears to have solved the original asker's problem, but the equivalent code in c# did not work for me. After trying increasingly complex annotations, going back to basics eventually did work. For everyone's reference, I include the declaration for three of the interface functions and working code (built against ssdeep version 2.9).
//Note: StringBuilder here is the standard way to do it, but is a perf hit because unicode stringbuilder can't be pinned when martialling char*.
//See http://msdn.microsoft.com/en-us/magazine/cc164193.aspx#S4
//int fuzzy_hash_buf(const unsigned char *buf, uint32_t buf_len, char *result)
[DllImport("fuzzy.dll")]
public static extern int fuzzy_hash_buf(StringBuilder buf, int buf_len, StringBuilder result);
//int fuzzy_hash_filename(const char* filename, char* result)
[DllImport("fuzzy.dll")]
static extern int fuzzy_hash_filename(string filename, StringBuilder result);
//int fuzzy_compare (const char *sig1, const char *sig2)
[DllImport("fuzzy.dll")]
static extern int fuzzy_compare(string sig1, string sig2);
static void Main(string[] args)
{
StringBuilder buf = new StringBuilder("test");
StringBuilder result0 = new StringBuilder(150);
fuzzy_hash_buf(buf, 4, result0);
Console.WriteLine(result0);
string filename = "test.txt";
StringBuilder result1 = new StringBuilder(150);
fuzzy_hash_filename(filename, result1);
Console.WriteLine(result1);
int matchScore = fuzzy_compare(result0.ToString(), result1.ToString());
Console.WriteLine("MatchScore: " + matchScore);
}
Output:
ssdeeptest.exe
3:Hn:Hn
24:gRnIM7stweRp+fEWU1XRk+/M98D6Dv3JrEeEnD/MGQbnEWqv3JW:gRIMwtrMU1Bk2I3Jrg53JW
MatchScore: 0
I am trying to build a dll that reads a text file to populate a 2d array, then change that array as needed. I'm using a VB GUI to access it. The overall program is a micromouse simulator in which the user is able to customize the wall placement in a 5x5 maze, as well as mouse start position and goal placement, and allow the search algorithm (dll) to solve it. Here's the code inside my dll:
/*testDLL.cpp*/
#include "testDLL.h"
#include <stdio.h>
FILE *maze;
char mazearray[12][12];
void _stdcall wallfunction(int x, int y){
maze = fopen ("C:\Users\Public\Documents\5x5mazedefault.txt", "r");
fread (mazearray, sizeof(mazearray), 1, maze);
fclose(maze);
if (mazearray[x][y] == 'X'){
mazearray[x][y] = ' ';
}
else if (mazearray[x][y] == ' '){
mazearray[x][y] = 'X';
}
}
I want to be able to put in two input variables as the index of the matrix and add or subtract a wall from that location. Whenever I try to call the function from VB, it sends me a message: PInvoke restriction cannot return variants. The function returns nothing, so I don't understand...
Here's the declaration statement inside my VB program:
Private Declare Function wallfunction Lib "C:\Path\Path\testDLL.dll" (ByVal x As Integer, ByVal y As Integer)
I'm aware I'm not going to be able to call the fread function everytime the user wants to change a wall; I'm just trying to get this working once first. Any thoughts?
Change Function to Sub in your Declare statement in VB. This is because your C++ function returns void.
Since moving to .net 4.0 from 2.0, I cannot run successfully the SetWindowsHookEx function. It always ends with the Win32 error number 1400: "Invalid window handle".
This is the pinvoke signature:
[DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowsHookExA", CharSet = CharSet.Ansi)]
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProcDelegate lpfn, int hModule, int dwThreadId);
This is the call:
SetWindowsHookEx(WH_KEYBOARD_LL, HookProc, iModule, 0);
It worked before. Why should it return with an "Invalid window handle" error anyway ?
btw: on windows 7 it works, but only if I set iModule = 0. on XP it doesn't work anyhow.
Problem solved:
The problem was the iModule. I assigned it this way:
int iModule = System.Runtime.InteropServices.Marshal.GetHINSTANCE(
System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0])
).ToInt32();
And the right way to do that, is apparently:
int iModule = System.Diagnostics.Process.GetCurrentProcess().MainModule.BaseAddress.ToInt32();
But I'll be glad to know the reason for that. Logically, the GetModules()[0] gives the dll file itself where the callback function resides, while GetCurrentProcess().MainModule.BaseAddress returns the main module (dll file ?), that may be different from the dll that holds the callback function.
So how come it actually works "the other way around" - according to my understanding ? and how come it worked until I changed the .net version ?