我制作了一个导出多个函数的 DLL(使用 stdcall)。我想让他们中的一些人接受或不接受参数。所以懒惰的程序员可以不带任何参数调用它。我在论坛上的某个地方读到默认参数在 DLL-s 中不起作用。我唯一的选择是创建 2 个具有不同名称的函数,例如:
procedure DoSomething();
begin
DoSomethingParams(1, 'Hi');
end;
procedure DoSomethingParams(one: Integer; two: PChar);
begin
//
end;
Run Code Online (Sandbox Code Playgroud)
? 或者也许有更优雅的方式来实现这一目标?
我为我的Unity3d应用程序用C++创建了一些插件文件.到目前为止,应用程序只是一个简单的原型,所以我只在我的桌面上测试编译为Windows的DLL库.今天我将这些文件重新编译为.so(共享对象)for Android(arm和x86)并收到警告消息.
警告:为此目标忽略调用约定'__stdcall'[-Wignored-attributes]
1.这意味着所有函数都编译为__cdecl?
2.我不能在.so库中指定调用约定吗?
我用__cdecl替换了__stdcall,但它也发生了一条警告消息.
这段代码编译(正如我所料):
typedef void __stdcall (*Func)();
struct A {
static void __stdcall f() { }
};
int main() {
Func p = A::f;
}
Run Code Online (Sandbox Code Playgroud)
但是这一个:
struct A {
typedef void __stdcall (*Func)();
static void __stdcall f() { }
};
int main() {
A::Func p = A::f;
}
Run Code Online (Sandbox Code Playgroud)
失败时出现不太有用的错误消息:
error: invalid conversion from `void (*)()' to `void (*)()'
Run Code Online (Sandbox Code Playgroud)
我在Vista下使用g ++ 3.4.2(我知道,它很古老,但我现在无法访问任何其他环境).显然我在这里遗漏了一些东西.任何帮助,将不胜感激.
这个问题从这个arised 一个.
问题是:创建非可视组件,可以从系统中保存许多回调命令.用户可以在IDE中定义无限数量的回调.回调将在TCollection中定义为TCollectionItem.
这是一种非常好的模式,但有一些缺点.(后面会说)因此我想知道,如果可以做得更好;-)
这是一个主要组件,用户可以通过CommandsTable集合在IDE中定义无限数量的回调函数
TMainComp = class(TComponent)
private
CallbacksArray: array [0..x] of pointer;
procedure BuildCallbacksArray;
public
procedure Start;
published
property CommandsTable: TCommandCollection read FCommandsTable write SetCommandsTable;
end;
Run Code Online (Sandbox Code Playgroud)
每个集合项都如下所示,InternalCommandFunction是回调函数,它是从系统调用的.(Stdcall呼叫公约)
TCommandCollectionItem = class(TCollectionItem)
public
function InternalCommandFunction(ASomeNotUsefullPointer:pointer; ASomeInteger: integer): Word; stdcall;
published
property OnEventCommand: TComandFunc read FOnEventCommand write FOnEventCommand;
end;
Run Code Online (Sandbox Code Playgroud)
TComandFunc = function(AParam1: integer; AParam2: integer): Word of Object;
Run Code Online (Sandbox Code Playgroud)
这是一个实现.整个过程可以通过"开始"程序开始
procedure TMainComp.Start;
begin
// fill CallBackPointers array with pointers to CallbackFunction
BuildCallbacksArray;
// function AddThread is from EXTERNAL dll. This function …Run Code Online (Sandbox Code Playgroud) Run Code Online (Sandbox Code Playgroud)__declspec(dllexport) int __stdcall TestFunktion(void) { return 0; }
在 Visual Studio 中是否有任何简单的方法可以创建没有修饰且没有 DEF 文件的函数?
我声明了一些C++函数原型如下:
extern "C" void __stdcall function();
Run Code Online (Sandbox Code Playgroud)
我也有一些第三方dll导出function()- 根本没有名字装饰.undefined reference to function@...由于MinGW的stdcall @ -suffix,我无法构建我的exe或dll .如何在没有@的情况下获取目标文件...只是简单的函数名称?
GetProcAddress()在 32 位 DLL 上使用的正确方法是什么?在 win32 上,共有三种调用约定,cdecl、stdcall 和 fastcall。如果 DLL 中的函数是foo他们将通过以下方式修饰名称_foo,_foo@N并且@foo@N。
但是如果 dll 的作者使用了 .def 文件,那么导出的名称将更改为“foo”,没有任何修饰。
这给我带来了麻烦,因为如果我想foo从使用 stdcall 的 dll加载,我应该使用装饰名称:
void *h = LoadLibraryEx(L"foo.dll", NULL, 0);
GetProcAddres((HMODULE)h, L"_foo@16");
Run Code Online (Sandbox Code Playgroud)
或未装饰的:
void *h = LoadLibraryEx(L"foo.dll", NULL, 0);
GetProcAddres((HMODULE)h, L"foo");
Run Code Online (Sandbox Code Playgroud)
? 我应该猜吗?我查看了很多 32 位 DLL 文件(stdcall 和 cdecl),它们似乎都导出了未修饰的名称。但是你能假设情况总是如此吗?
winapi calling-convention stdcall getprocaddress name-decoration
我创建了一个DLL文件,其中包含两个空函数.
extern "C" __declspec(dllexport) void __stdcall myFunc1() {
// just empty function
}
extern "C" __declspec(dllexport) void __cdecl myFunc2() {
// just empty function
}
Run Code Online (Sandbox Code Playgroud)
在C#中,我可以使用DLLImport如下属性调用函数.
[DllImport("myDLL", CallingConvention=CallingConvention.StdCall)]
private extern static void myFunc1();
[DllImport("myDLL", CallingConvention=CallingConvention.Cdecl)]
private extern static void myFunc2();
Run Code Online (Sandbox Code Playgroud)
所以我再次尝试使用LoadLibrary()kernel32.dll而不是DllImport属性.
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void MyFunc1();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void MyFunc2();
Run Code Online (Sandbox Code Playgroud)
但是,当我调用MyFunc1()工作时MyFunc1()时会发生运行时错误.
所以我__stdcall用__cdeclC++ 替换,重新编译DLL,然后在C#中再次调用MyFunc1().
并且......它奏效了.
为什么地球上没有__stdcall呼叫约会在C#中用pinvoke工作?
我一直在阅读有关汇编函数的内容,我对是否使用enter和exit或只是使用call/return指令进行快速执行感到困惑.一路快,另一路小吗?例如,在没有内联函数的情况下,在汇编中执行此操作的最快(stdcall)方法是什么:
static Int32 Add(Int32 a, Int32 b) {
return a + b;
}
int main() {
Int32 i = Add(1, 3);
}
Run Code Online (Sandbox Code Playgroud) 我想通过以下方式管理 WinAPI 函数对std::unique_ptr:
#include <memory>
int* __stdcall construct(){ return new int{5}; }
void __stdcall destruct(int* v){ delete v; }
int main() {
using Ptr = std::unique_ptr<int, void(&)(int*)>;
Ptr v(construct(), destruct);
}
Run Code Online (Sandbox Code Playgroud)
当我使用 MSVC 19.33 构建 64 位二进制文件时,代码可以正常工作。如果我构建 32 位二进制文件,则会出现错误。
example.cpp
<source>(8): error C2660: 'std::unique_ptr<int,void (__cdecl &)(int *)>::unique_ptr': function does not take 2 arguments
C:/data/msvc/14.33.31631/include\memory(3291): note: see declaration of 'std::unique_ptr<int,void (__cdecl &)(int *)>::unique_ptr'
Compiler returned: 2
Run Code Online (Sandbox Code Playgroud)
__stdcall如果我明确命名in ,它适用于两者std::unique_ptr<int, void(__stdcall&)(int*)>,所以我假设它是函数签名的一部分。
为什么 32 位和 64 位会有这种差异?这是编译器中的错误吗?