gpt4 book ai didi

c# - 在C#中动态调用不同的C DLL

转载 作者:行者123 更新时间:2023-11-30 20:29:05 26 4
gpt4 key购买 nike

我目前正在用 C# 创建一个 Windows 窗体应用程序,其中需要在运行时通过文件对话框在应用程序中调用用 C 编写的具有自己的结构和函数的不同 .dll 文件以获得它们的路径。据我了解,这意味着我无法使用 [DllImport("filename")],因为路径值在编译时尚未确定。我至少得到了 .h 文件,并且还保证导出的函数具有相同的名称。

我在网上搜索了很多不同的帖子,大多数解决方案最终都指向 PInvoke、Reflection 和/或 InteropServices,但没有明确的示例说明该怎么做。

由于每个这样的 dll 定义了自己的结构,我希望能够:1. 使用 dll 本身的结构定义以避免在 C# 中重新定义所有内容,2. 加载dll后,在应用程序的不同点使用函数。

诚然,我对 C# 很陌生,所以我上面尝试做的事情可能根本不可能。但我现在很茫然,因为我找不到从哪里开始学习来解决这个问题。任何帮助将不胜感激。

引用代码如下:

dll 的头文件之一 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_ */

以及 C# 文件 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?
}
...
}

最佳答案

在回答你的第一个问题时,我不知道有什么方法可以直接从 dll 获取结构定义。 (尝试 LoadLibrary、GetProcAdres),但为调试而构建的可能异常(exception)。如果您知道将在 C 中使用的结构,那么它应该非常简单定义在 C# 中使用的结构 - pinvoke.net 等网站上有很多示例。

例如C中的这个函数声明:

__declspec(dllexport) int scrypt(const uint8_t * passwd, size_t passwdlen, 
const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r,
uint32_t p,uint8_t * buf, size_t buflen);

可以转化为:

[DllImport("SCrypt.dll", CharSet = CharSet.Unicode, 
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern int scrypt(byte[] passwd, uint passwdlen, byte[] salt, uint saltlen,
ulong N, uint r, uint p, byte[] buf, uint buflen);

其次,您可以在使用程序之前尝试将 dll 复制到已知位置(例如执行目录)。使用适当的 dll 编译代码然后就可以工作了。当然,这种技术假设你知道你要使用的 dll提前引用。

关于c# - 在C#中动态调用不同的C DLL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59079363/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com