I'm currently creating a Windows Form application in C#, where different .dll files written in C with their own structs and functions need to be called in the application at runtime through a file dialog to obtain their path. To my understanding, this means that I cannot use [DllImport("filename")]
, since the path values are not determined at compile time. I'm at least given the .h files, and also a guarantee that the exported functions will have the same name.
I've scoured through a lot of different posts online, and most of the solutions pointed eventually towards PInvoke, Reflection and/or the InteropServices, but with no clear examples on what to do.
Since each such dll defines their own structs, I'd like to be able to: 1. Use the struct definition from the dll itself to avoid redefining everything in C#, 2. Use the functions at different points in the application after loading the dll.
Admittedly, I am very new at C#, so what I am trying to do above might not even be possible. But I'm at a loss right now, as I cannot find where to even begin start learning in order to address this problem. Any help would be greatly appreciated.
Here's the code for reference:
One of the dlls' header files classifier.h:
#ifndef SRC_CLASSIFIER_H_
#define SRC_CLASSIFIER_H_
#include "vector.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef BUILD_DYNAMIC_LIB
#ifdef _WIN32
#define _EXPORT __declspec(dllexport)
#else
#define _EXPORT __attribute__((visibility("default")))
#endif
#else
#define _EXPORT
#endif
/** Error codes */
#define CLASSIFIER_OK 0x00
#define CLASSIFIER_INIT_MISSING 0x01
#define CLASIFIER_NO_SAMPLES_PROVIDED 0x02
#define CLASSIFIER_PARAM_OUT_OF_RANGE 0x03
#define CLASSIFIER_DECISION_BUFFER_LEN 20
#define CLASSIFIER_MAX_BURST_LEN 32
typedef struct {
uint8_t sensitivity;
uint8_t noTruckRecognitionLimit;
uint8_t noTruckRecognitionHyst;
uint16_t intensityLimit[CLASSIFIER_MAX_BURST_LEN];
} classifier_Parameter_t;
typedef enum { UNDEFINED = 0x00, TRUCK = 0x01, NO_TRUCK = 0x02 } class_t;
typedef struct {
class_t classifiedAs;
} classifier_Result_t;
typedef struct {
uint8_t noOfSamples;
vec3d_t accSamples[CLASSIFIER_MAX_BURST_LEN];
} classifier_Input_t;
_EXPORT uint8_t classifier_api_Init(classifier_Parameter_t *para);
_EXPORT uint8_t classifier_api_Execute(classifier_Input_t *input,
classifier_Result_t *result);
_EXPORT uint8_t classifier_api_Reset(void);
#ifdef __cplusplus
}
#endif
#endif /* SRC_CLASSIFIER_H_ */
And the C# file MainForm.cs:
using System;
...
namespace ClassifierEval
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void btnLoadDll_Click(object sender, EventArgs e)
{
openFileDialogLoadDll.ShowDialog();
}
private void openFileDialogLoadDll_FileOk(object sender, CancelEventArgs e)
{
lblLoadedDll.Text = openFileDialogLoadDll.FileName;
///Loading the DLL here?
}
...
}