- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在考虑为名为 SmartDVB 的软件编写插件。它需要我导出以下函数(这是一个 C++ 示例):
BOOL RegisterAddOn(UINT iAddOnId, IAddOnInterfaces *pInt, AddOnSettings &settings) {
/* ... */
return TRUE;
}
其中IAddonInterfaces
是一个抽象类(接口(interface)):
class IAddOnInterfaces {
public:
virtual HRESULT AddSectionFilter(UINT uiAddOnId, UINT pid, BYTE *filter, BYTE *mask, BYTE length, DeviceSettings *pDev) = 0;
virtual HRESULT RemoveSectionFilter(UINT uiAddOnId, UINT pid, DeviceSettings *pDev) = 0;
virtual HRESULT AddFilter(UINT uiAddOnId, UINT pid, DeviceSettings *pDev=NULL) = 0;
virtual HRESULT RemoveFilter(UINT uiAddOnId, UINT pid, DeviceSettings *pDev=NULL) = 0;
virtual HRESULT GetChannel(UINT uiAddOnId, CHANNEL *chn, DeviceSettings *pDev=NULL) = 0;
virtual HRESULT GetTransponder(UINT uiAddOnId, SATELLITE *sat, TRANSPONDER *t, DeviceSettings *pDev=NULL) = 0;
virtual HRESULT SetTransponder(UINT uiAddOnId, SATELLITE sat, TRANSPONDER t, DeviceSettings *pDev=NULL) = 0;
virtual HRESULT CreateOSDElement(UINT uiAddOnId, OSDWindowType type, ULONG &ulId, OSDWindowInfo &info) = 0;
virtual HRESULT ChangeChannel(UINT uiAddOnId, CHANNEL &chn, DeviceSettings *pDev=NULL) = 0;
virtual HRESULT RegisterOSDEvents(UINT iAddOnId, IAddOnOSDEvents *pEvents) = 0;
virtual HRESULT RegisterMenuEvents(UINT iAddOnId, IAddOnMenuEvents *pEvents) = 0;
virtual HRESULT RegisterChnEvents(UINT iAddOnId, IAddOnChnEvents *pEvents) = 0;
virtual HRESULT DoDVBCmd(UINT iAddOnId, BYTE pCmd, UINT uiLen, DeviceSettings *pDev=NULL) = 0;
virtual HRESULT DoDiseqc(UINT iAddOnId, CHANNEL &chn, DeviceSettings *pDev=NULL) = 0;
virtual HRESULT RecordBusy(UINT iAddOnId, BOOL *bBusy, DeviceSettings *pDev=NULL) = 0;
virtual HRESULT GetDeviceSettings(UINT iAddOnId, DeviceSettings &Dev) = 0;
virtual HRESULT GetSignalStrength(UINT iAddOnId, LONG *lStrength, DeviceSettings *Dev) = 0;
virtual HRESULT GetSignalQuality(UINT iAddOnId, LONG *lQuality, DeviceSettings *Dev) = 0;
};
AddOnSettings
是一个结构体:
typedef struct _AddOnSettings{
HINSTANCE hInst; // SmartDVB application instance
HWND hwnd;
TCHAR name[256]; // addon name
HMENU menu; // addon popup menu
WORD idmenustart;
} AddOnSettings;
在c#中,我将结构定义为
using HINSTANCE = System.IntPtr;
using HWND = System.IntPtr;
using HMENU = System.IntPtr;
/* ... */
public unsafe struct AddOnSettings{
HINSTANCE hInst; // SmartDVB application instance
HWND hwnd;
[MarshalAs(UnmanagedType.LPArray, SizeConst = 256)]
char[] name; // addon name
HMENU menu; // addon popup menu
ushort idmenustart;
};
/* ... */
但是,我仍然需要以某种方式定义类,以便可以将其导出。
最后,我想要这样的东西:
[DllExport("RegisterAddOn", CallingConvention = CallingConvention.Cdecl)]
public static bool RegisterAddOn(uint iAddOnId, IAddOnInterfaces* pInt, ref AddOnSettings settings)
{
/* ... */
return true;
}
问题是,当我这样做时,出现以下错误:
Error 1 Cannot take the address of, get the size of, or declare a pointer to a managed type ('ChannelSwitchCS.IAddOnInterfaces') D:\Work\coding\projects\buster\smartdvb\ChannelSwitchCS\ChannelSwitchCS\Class1.cs 102 28 ChannelSwitchCS
附言我不要求完整的解决方案,我只需要了解这种特殊情况,即如何(以及是否可能)在导出函数中拥有指向类实例的指针。因此,我确实意识到我将不得不转换在 IAddOnInterfaces
的方法中使用的所有其他结构和类。
最佳答案
当我不得不使用 PInvoke 并且需要将类的实例作为指针传递时,我为我将在 C++ 中使用的非托管代码编写了一个简单的包装器,它只接受原始类型并将它们排列成任何类型需要。
在将指针传递给类的实例时,我使用了 IntPtr
,一切都按照我的预期进行。
关于C#:Cdecl DllExport,参数中带有指向类实例的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28805100/
我在 Linux x86 上使用 gcc。 我的程序将指向 C 函数的指针导出到 LLVM JIT 函数。调用约定是 cdecl。它在 Windows 上的 MingW 上运行良好。但是奇怪的事情发生
在一篇关于 _cdecl 调用约定的文章中,作者提到: Release local storage When the function allocates local, temporary space
我有希望根据某些输入调用的函数。每个函数都有不同数量的参数。换句话说, if (strcmp(str, "funcA") == 0) funcA(a, b, c); else if (strcmp(s
我正在使用 g++ 编写一个 64 位操作系统,并且我有一个可变参数函数,例如: void DbgPrint(const char *fmt, ...); 其行为与 printf 非常相似。这里的问题
发件人:http://en.wikipedia.org/wiki/X86_calling_conventions push c push b push a call function_name add
是的,我知道“cdecl”是一个重要的调用约定的名称,所以请不要向我解释调用约定。我要问的是缩写(?)“cdecl”实际上代表什么。我认为这是一个糟糕的命名选择,因为乍一看它让人想起“C 声明符”
有(除其他外)两种类型的调用约定 - stdcall 和 cdecl。我对他们有几个问题: 调用cdecl函数时,调用者如何知道它是否应该释放堆栈?在调用现场,是否调用者知道被调用的函数是 cdecl
我正在阅读 IDA Pro Book .在讨论调用约定的第 86 页上,作者展示了一个 cdecl 调用约定示例,它消除了调用者从堆栈中清除参数的需要。我正在重现下面的代码片段: ; demo_cde
我一直在玩cdecl我注意到有些名称不允许作为标识符,尽管 GCC 可以完美地编译它们。 例如,如果我写 int ptr; 或 int pointer; 或 int array; cdecl 给出了“
我的应用程序崩溃了,因为我调用的库函数更改了 ESP,尽管它被声明为 cdecl。 库 (libclang.dll) 是使用 MinGW 编译的,我在 VC++ 项目中使用它。这些函数作为 C 函数导
嗨我的 VC2008 项目使用 stdcall 调用约定。我有一个我正在使用的外部库,它是用 cdecl 命名约定构建的,但是他们没有在函数的函数声明中提到调用约定。 我想知道 VC 是否有某种 #p
我正在考虑为名为 SmartDVB 的软件编写插件。它需要我导出以下函数(这是一个 C++ 示例): BOOL RegisterAddOn(UINT iAddOnId, IAddOnInterface
我最近一直在尝试通过使用缓冲区和不同汇编运算符的 RAW 十六进制等价物在 C++ 中实现动态函数。为了说明一个简单的跳转: byte * buffer = new buffer[5]; *buffe
在海湾合作委员会 cdecl调用约定,在调用返回后,我是否可以依赖我压入堆栈的参数相同?即使混合 ASM 和 C 并启用优化( -O2 )? 最佳答案 一句话:没有。 考虑这个代码: __cdecl
检查这个demo source来自优秀的 Detour 库: implementation {$R *.dfm} var TrampolineGetMemory: function(Size: N
有人要求我更改一些 __asm 代码,以便它实现 C++ 调用约定。我试过使用 cdecl 但我一直收到此错误 Run-Time Check Failure #0: The value of ESP
我有一个最初用 MSVS 编写的库 (dll),我需要跨平台 (Mac/Win)。我开始使用 XCode,但有了新的 Embarcadero C++ 构建器 XE3,我认为一个开发环境会是更好的方法。
大家好,我是汇编语言 x86 的新热心学习者,我正在尝试从一组加密指令生成 CDECL 调用约定。我相信我在执行公约的过程中出错了。以下是作为问题给出的原始指令集和函数。还包括我的尝试(如果它对汇编语
我正在尝试使用具有回调机制的 (C) 第三方库,该机制缺少任何可能的识别调用上下文的方法。我的主要项目在 C# 中,我的包装器是一个调用 C 库 API 的 C++/CLI 项目。 为了解决这个问题,
有人可以给我一些为 MS winapi 函数创建函数指针的技巧吗?我正在尝试为 DefWindowProc (DefWindowProcA/DefWindowProcW) 创建指针,但出现此错误: L
我是一名优秀的程序员,十分优秀!