C
C#acookook

❔ Problem with including C DLL in a C# console app project.

So I have this C DLL imported into my console app (.NET 5). I simply cannot get to call it correctly, since everytime I get, something along the lines, that something with the entrypoint is broken, like: System.EntryPointNotFoundException: 'Unable to find an entry point named 'getCalculatedFitting' in DLL 'BPCalculationDLL.dll'.' The code with which I am defining this is [DllImport("BPCalculationDLL.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "getCalculatedFitting")] public static extern int getCalculatedFitting(float[] fittinglData, uint length, char ch); Honestly I tried a few things, but none of them seem to work in the current VS2022 editor. Does anyone have any idea how import this DLL and call it in another function?
K
Kouhai /人◕ ‿‿ ◕人\397d ago
use dll viewer or dependency walker and check the exported symbols
A
acookook397d ago
It looks like it is a C++ function after all. So what to include in the DLL import tag?
A
Accord396d ago
Looks like nothing has happened here. I will mark this as stale and this post will be archived until there is new activity.
A
acookook394d ago
Ok, I managed to get to work, but I am getting a System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.' The function i tried to import is something along the lines //private static extern int calculateBP(ushort[] data, uint len, char ch, uint samplingRate, IntPtr results); or //private static extern int calculateBP(out ushort[] data, uint len, char ch, uint samplingRate, IntPtr results); //private static extern int calculateBP(ref ushort[] data, uint len, char ch, uint samplingRate, ref Measurement[] results);defined as int CalculateBP(USHORT * data, UINT len, UCHAR ch, UINT samplingRate, measurement * results); I triend numerous things, including to allocate some memmory using marshal, but still no luck. Any idea how to debug and solve this. The measurement struct contains a number of floatsand integers which I have also defined, but apparently I can't call it correctly.
J
Jimmacle394d ago
it would help to see both the C++ function signature and struct definition and C# struct definition and marshalling code first thing i see is your data types are probably wrong and i don't believe [DllImport] automatically marshals arrays for you
A
acookook394d ago
The C++ function as defined in the header file is the following: __declspec(dllexport) int CalculateBP(USHORT * data, UINT len, UCHAR ch, UINT samplingRate, measurement * results); while the DLL import is the following: [DllImport("BPCalculationDLL.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?CalculateBP@@YAHPAGIEIPAUmeasurement@@@Z")] The C is defined by typedef struct{ float val1; float val2; int numBettween; int error; } measurement; I meant by marshaling is that is tried to use methods to deal with unmanaged code (from the System.Runtime.InteropServices.Marshal namespace), but to no success. I also trie some combinations mentioned on SO (https://stackoverflow.com/questions/28595903/copy-from-intptr-16-bit-array-to-managed-ushort), but no success.
Stack Overflow
Copy from IntPtr (16 bit) array to managed ushort
I have a IntPtr called rawbits, which points to a 10MB array of data, 16 bit values. I need to return a managed ushort array from that. The following code works but there is an extra BlockCopy I wo...
J
Jimmacle394d ago
not just the dllimport attribute, the whole method signature
A
acookook394d ago
so as I defined it in C#?
J
Jimmacle394d ago
right
A
acookook394d ago
J
Jimmacle394d ago
first thing is C++ chars aren't the same as C# chars, the former is 1 byte and the second is 2 bytes
A
acookook394d ago
I tried multiple approaches with multiple combinations, but none of the seem to give the desired result
J
Jimmacle394d ago
second you can't pass arrays to unmanaged code like that, the GC could move them while the unmanaged code is trying to work with them and that would be Bad they have to be pinned if you use the new-ish LibraryImport attribute instead of DllImport it can generate that code for you
A
acookook394d ago
oh, I understand How exactly do I do that?
J
Jimmacle394d ago
it's more or less just replacing the attribute
J
Jimmacle394d ago
A
acookook394d ago
oh, nevermind is this something in .net 7 only?
J
Jimmacle394d ago
yeah
A
acookook394d ago
ok then I need first to upgrade to .net 7 from 5
J
Jimmacle394d ago
if you can you might as well if not you can hand-write the same code that LibraryImport would generate
A
acookook394d ago
ok, so now i have this
A
acookook394d ago
A
acookook394d ago
an 3 errors
K
Kouhai /人◕ ‿‿ ◕人\394d ago
You need to specify which parameter is used for the array's size @šanji
A
acookook394d ago
like that?
A
acookook394d ago
[MarshalAs(unmanagedType: UnmanagedType.LPArray)] ushort[] data
K
Kouhai /人◕ ‿‿ ◕人\394d ago
No like, [MarshalAs(SizeParamIndex=1)] ushort[] data iirc default marshaling for arrays is already LPArray,
A
acookook394d ago
ok, so i am actuall more lost that I was before
K
Kouhai /人◕ ‿‿ ◕人\394d ago
😅 Okay, SizeParamIndex just specifies that the parameter index we'll use to indicate the length of the array data is at position 1 which is uint len
A
acookook394d ago
this just gives me an error
K
Kouhai /人◕ ‿‿ ◕人\394d ago
oops sorry [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
A
acookook394d ago
no problem
A
acookook394d ago
So i just need to figure out this
A
acookook394d ago
nevermin, it's a byte ok...I think I got it. private static partial int calculateBP([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ushort[] data, uint len, [MarshalAs(UnmanagedType.U1)] byte ch, uint samplingRate, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Measurement[] results); So now just need to pass in the neccessarry data and any empty measurement array of structs and I am golden? Do I need to worry if that the data is processed by other functions of the DLL and then that data can be corrupt? Ok, I definitely need to think deeper, since I get invalid measurement results out of the function, and also other functions return invalid data.
K
Kouhai /人◕ ‿‿ ◕人\393d ago
Can you show your C++ definition? I guess you've already sent it I think you're misunderstanding what passing an array by ref means passing an array by ref is basically passing a pointer to the array ref int[] is the equivalent of int** in C/C++
A
acookook393d ago
yeah I just would like to finally solve this issue. Although I fixed the DLL importing issue, I probably just too plug in different numbers
A
Accord392d ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
A
acookook392d ago
Ok, so it seems that I magnaged VS no to crash on the call of the function, but something just doesn't seem right since i don't get the expected values in other functions
K
Kouhai /人◕ ‿‿ ◕人\392d ago
Hmmm, Are you still passing ref arrays?
A
acookook392d ago
getCalculatedFittingSize(UCHAR ch) is always returning zero, but anything above should be the result. The c# call is th following. private static partial int getCalculatedFittingSize([MarshalAs(UnmanagedType.U1)] byte cuffNumber); so now I am having the the function defined as private static partial int CalculateBP([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ushort[] data, uint len, [MarshalAs(UnmanagedType.U1)] byte cuffNumber, uint samplingRate, ref Measurement result); and calling it as CalculateBP(dataToUShort, (uint)dataToUShort.Length, 0, samplingRate, ref result);
K
Kouhai /人◕ ‿‿ ◕人\392d ago
Okay, first are you 100% sure the C++ method produces the correct results?
A
acookook392d ago
yes, the same underlying code is used else where, so i am sure it is my C# code, not the C++ code.
K
Kouhai /人◕ ‿‿ ◕人\392d ago
Can you show your Measurement struct? Both C# and C++
A
acookook392d ago
the c++ struct is here https://discord.com/channels/143867839282020352/1090377331970949250/1091780654854840512 and C# stuct is [StructLayout(LayoutKind.Sequential)] public struct Measurement { [MarshalAs(UnmanagedType.R4)] float sys; [MarshalAs(UnmanagedType.R4)] float dia; [MarshalAs(UnmanagedType.R4)] float max; [MarshalAs(UnmanagedType.R4)] float amp; [MarshalAs(UnmanagedType.R4)] float hr; [MarshalAs(UnmanagedType.I4)] int maxIdx; [MarshalAs(UnmanagedType.I4)] int err; }
K
Kouhai /人◕ ‿‿ ◕人\392d ago
which fields have wrong values?
A
acookook392d ago
based on the c++ logic (which is not documented I can't say for sure, but since the int err is always zero, the values do not break the code or result in an error
K
Kouhai /人◕ ‿‿ ◕人\392d ago
Unfortunately that's not how it'll work Because your struct is different from this
typedef struct{
float val1;
float val2;
int numBettween;
int error;
} measurement;
typedef struct{
float val1;
float val2;
int numBettween;
int error;
} measurement;
This struct's error is at offset 0xC Meanwhile your 0xC offset is for amp The offsets are basically like this
typedef struct{
float val1; // 0x0
float val2; // 0x4
int numBettween; // 0x8
int error; // 0xC
} measurement
typedef struct{
float val1; // 0x0
float val2; // 0x4
int numBettween; // 0x8
int error; // 0xC
} measurement
public struct Measurement
{
[MarshalAs(UnmanagedType.R4)]
float sys; // 0x0

[MarshalAs(UnmanagedType.R4)]
float dia; // 0x4

[MarshalAs(UnmanagedType.R4)]
float max; // 0x8

[MarshalAs(UnmanagedType.R4)]
float amp; // 0xC

[MarshalAs(UnmanagedType.R4)]
float hr; // 0x10

[MarshalAs(UnmanagedType.I4)]
int maxIdx; // 0x14

[MarshalAs(UnmanagedType.I4)]
int err; // 0x18
}
public struct Measurement
{
[MarshalAs(UnmanagedType.R4)]
float sys; // 0x0

[MarshalAs(UnmanagedType.R4)]
float dia; // 0x4

[MarshalAs(UnmanagedType.R4)]
float max; // 0x8

[MarshalAs(UnmanagedType.R4)]
float amp; // 0xC

[MarshalAs(UnmanagedType.R4)]
float hr; // 0x10

[MarshalAs(UnmanagedType.I4)]
int maxIdx; // 0x14

[MarshalAs(UnmanagedType.I4)]
int err; // 0x18
}
A
acookook392d ago
yeah, my mistake...I was truncationg it,just to write minimum code the C# fields are present in C++ also
K
Kouhai /人◕ ‿‿ ◕人\392d ago
Huh, so CalculateBP should run okay then
A
acookook392d ago
so basically my values are messed up?
K
Kouhai /人◕ ‿‿ ◕人\392d ago
I honestly don't see what could fail, if you have the access to the source code you could step into it and see what happens after marshaling
A
acookook392d ago
is there a way to debug this DLL code? I mean like calling it from C#
K
Kouhai /人◕ ‿‿ ◕人\392d ago
Assuming you're using visual studio you just have to enable this on your launch profile
K
Kouhai /人◕ ‿‿ ◕人\392d ago
A
Accord391d ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
A
acookook390d ago
Ok, so managed to get it to work, but after a few files have been successfully processed, I just a NullReferenceException and an Unable ro read memory in the "Watch" tab for the needed array. My guess is that i ran out of addressable memory. How to overcome that?
K
Kouhai /人◕ ‿‿ ◕人\390d ago
Why are you assuming you're running out of addressable memory? 😅
A
acookook390d ago
Because I can easily process a few files without any issues First I thought a file was corrupt, but then I tried out a new, independent set of files Apparently it is the last file that is being processed and the last data structure in this file.
UU
Unknown User390d ago
A
Accord389d ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server
More Posts
✅ Win Form Event Handlers questionHi, I was just wondering if there is an event handler when the win form is idle that I can then run ❔ Problem with Dictionary<ulong, Image> (Strange work of memory access)Concept of my system: A system that draws a picture with stickers, each of the stickers can be moved❔ How do I refactor this?I am working with a grid of tiles, each tile has an int, which is made up of 4 bytes which represent❔ [AvaloniaUI] Visibility of item in ListView based on conditionAn Avalonia UI application is used to manage an evidence of items. It allows the user to add items. ✅ How to structure this login/signup page layoutSo I have this mockup of the layout I want for a login/signup page in my Blazor WASM app. Pretty sta❔ I am need of help before I give up and run my code on a server instead of a serverless solution.I have create an azure function locally and i've used the selenuim webdriver package for taking scre✅ .Net Core 6 Asymmetric Encryption with custom public and private keysHello all! How can i use the `Asymmetric Encryption` in .Net 6 but choosing/importing private and pu❔ No Design in C#Instances of this bug (1) 1. View Call Stack at System.Runtime.InteropServices.Marshal.ThrowExce❔ having issues on a reloading script on unity to reload weaponsthe code is used in a youtube video and i have pretty much copied to to get it to work but it doesnt❔ help with an exerciseI've encountered a weird problem that idk how to fix. Say we've got a string "31131123521" how do i ❔ Accessing HTTP Context at DbCommandInterceptor [.NET 7]Hi! I'm having some issues trying to access the HTTP Context at my DbCommand Interceptor class. What❔ XMLAttributeCollection -> Dictionary with LINQ?It's a confusing class. It only allows turning it into a Queryable, but I have no experience with th❔ MS SQL Reporting Server URL Being RedirectedWe have an application from a vendor that was written in C# and we recently upgraded the MS SQL data❔ dataset memory leakI found memory leak and I don't understand how to fix it Test case: ```cpp public class MemoryLeaksT❔ WebAPI .NET 7.0 - Encrypt connectionstring in appsettings.jsonguys, I'm writing some WebAPI using .NET 7.0, and I'd like to secure the connectionstring with encry❔ how to read strings correctly with System.Data.SQLitei m trying read turkish characters from database but i can't see correctly❔ Blazor server app, base url / base page to set environmentHi 🙂 I have a Blazor Server app, where I would like to use some dynamic baseurl. Say instead of my❔ C# Console Application -its only writing the same random string, how can i make it do different ones?❔ Rapid prototypingDo you feel there is such a thing as rapid prototyping or mvp development where you do things differ❔ HotChocolate with IQueryable, apply a required filter on the ef entityBasically, I'm trying to find a way to configure an `IObjectFieldDescriptor` by adding a required ar