我已经构建了一个C++ DLL,我想用C#代码调用它.我可以调用一个函数,但是当C#代码尝试加载dll时,另一个抛出异常.
标题看起来像这样:
extern "C" __declspec(dllexport) BOOL Install();
extern "C" __declspec(dllexport) BOOL PPPConnect();
Run Code Online (Sandbox Code Playgroud)
这会产生一个带有轻微混乱的导出表的dll(名称字段中的foo = foo是什么意思?):
File Type: DLL
Section contains the following exports for PPPManager.dll
00000000 characteristics
499F44F0 time date stamp Fri Feb 20 16:04:00 2009
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 000078E4 Install = Install
2 1 000079DC PPPConnect = PPPConnect
Run Code Online (Sandbox Code Playgroud)
我的P/Invoke声明如下所示:
[DllImport("PPPManager.dll")]
private static extern bool Install();
[DllImport("PPPManager.dll")]
private static extern bool PPPConnect();
Run Code Online (Sandbox Code Playgroud)
对Install的调用没有异常返回,但是当我调用PPPConnect时,我得到一个MissingMethodException …
如何WSAGetLastError()从WinAPI 调用,以便获得有效的文本错误?
希望这是一个无脑的简单问题,但它表明我缺乏C++专业知识.我是一名C#程序员,过去我和其他人的C++/C dll一起完成了P/Invoke的大量工作.但是,这次我决定自己编写一个包装器C++ DLL(非托管),然后从C#调用我的包装器dll.
我遇到的问题是我无法定义可以通过p/invoke找到的C++函数.我不知道这是什么语法,但这是我到目前为止所做的:
extern bool __cdecl TestFunc()
{
return true;
}
Run Code Online (Sandbox Code Playgroud)
最初我只是这个,但它也没有用:
bool TestFunc()
{
return true;
}
Run Code Online (Sandbox Code Playgroud)
然后在C#方面,我有:
public const string InterfaceLibrary = @"Plugins\TestDLL.dll";
[DllImport( InterfaceLibrary, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "TestFunc" ), SuppressUnmanagedCodeSecurity]
internal static extern bool TestFunc();
Run Code Online (Sandbox Code Playgroud)
所有东西都编译,但是当我执行这个C#p/invoke调用时,我得到一个System.EntryPointNotFoundException:无法在DLL'Plugins\TestDLL.dll'中找到名为'TestFunc'的入口点.
当然,这在C++端必须非常简单,我只是不知道它的语法.
我正在使用以下代码来调用TaskDialog.
[DllImport("ComCtl32", CharSet = CharSet.Unicode, PreserveSig = false)]
internal static extern void TaskDialogIndirect(
[In] ref TASKDIALOGCONFIG pTaskConfig,
[Out] out int pnButton,
[Out] out int pnRadioButton,
[Out] out bool pfVerificationFlagChecked);
Run Code Online (Sandbox Code Playgroud)
但是,我得到异常"无法在DLL'ComCtl32'中找到名为'TaskDialogIndirect'的入口点."
我拿了这个代码.我使用的是Windows 7 x64(RC).
我究竟做错了什么?
我已经尝试用c#代码改变我的系统的时区几天了,而我正在尝试的任何东西都没有多大意义或工作.我开始尝试使用我在其他问题上看到的SetTimeZoneInformation的PInvoke语法.
[DllImport("kernel32.dll", CharSet = CharSet.Auto)] private static extern bool
SetTimeZoneInformation([In] ref TimeZoneInformation lpTimeZoneInformation);
Run Code Online (Sandbox Code Playgroud)
我正在研究如何创建TimeZoneInformation结构并因为我的系统显然具有动态DST系统而感到困惑.事实证明,自从微软Vista添加了一种处理时区的新方法以来.您现在必须使用SetDynamicTimeZoneInformation
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool SetDynamicTimeZoneInformation([In] ref DynamicTimeZoneInformation lpTimeZoneInformation);
Run Code Online (Sandbox Code Playgroud)
我在msdn上搜索了这个API的帮助,发现了一些问题,"应用程序必须具有SE_TIME_ZONE_NAME特权才能使此功能成功." 最终我发现这个页面看起来像是一个很好的代码来完成这个.问题是它不起作用.
这是我的非工作代码:
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public int LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_PRIVILEGES
{
public LUID Luid;
public UInt32 Attributes;
public UInt32 PrivilegeCount;
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct SystemTime
{
public ushort Year;
public ushort Month;
public ushort DayOfWeek;
public ushort Day;
public ushort Hour;
public ushort …Run Code Online (Sandbox Code Playgroud) 在VS2010中,如果使用错误的调用约定调用函数,则托管调试助手将为您提供pInvokeStackImbalance异常(pInvokeStackImbalance MDA),这通常是因为在调用C库时未指定CallingConvention = Cdecl.比如你写的
[DllImport("some_c_lib.dll")]
static extern void my_c_function(int arg1, int arg2);
Run Code Online (Sandbox Code Playgroud)
代替
[DllImport("some_c_lib.dll", CallingConvention=CallingConvention.Cdecl)]
static extern void my_c_function(int arg1, int arg2);
Run Code Online (Sandbox Code Playgroud)
因此获得了StdCall调用约定而不是Cdelc.
如果你回答这个问题,你已经知道了这个差异,但是对于这个线程的其他访问者:StdCall意味着被调用者清除堆栈中的参数,而Cdecl意味着调用者清理堆栈.
因此,如果您的C代码中的调用约定错误,则您的堆栈不会被清理并且程序崩溃.
但是,即使.NET程序使用StdCall进行Cdecl功能,.NET程序似乎也不会崩溃.默认情况下,VS2008上没有启用堆栈不平衡检查,因此一些VS2008项目使用了他们的作者不知道的错误调用约定.我刚尝试过GnuMpDotNet,即使缺少Cdelc声明,样本运行也很好.X-MPIR也是如此.
它们都在调试模式下抛出pInvokeStackImbalance MDA异常,但在发布模式下不会崩溃.为什么是这样?.NET VM是否将所有对本机代码的调用包装起来并在之后恢复堆栈本身?如果是这样,为什么还要使用CallingConvention属性呢?
我在jar文件中有一个Java API,其中包含一些来自其他jar文件的依赖项.
有没有办法从这个API调用一个特定的方法,比如使用.NET的PInvoke?
谢谢.
我想通过c#/ PInvoke调用GetLogicalProcessorInformation函数,但是我坚持使用SYSTEM_LOGICAL_PROCESSOR_INFORMATIONstruct和CACHE_DESCRIPTORstruct.
我该如何定义这些结构以便正确使用?
主要表现在:
1.SYSTEM_LOGICAL_PROCESSOR_INFORMATION有工会在其定义
2. SYSTEM_LOGICAL_PROCESSOR_INFORMATION具有ULONGLONG在其定义
3. CACHE_DESCRIPTOR具有WORD与DWORD在它的定义.
你能帮我解决这些问题吗?
我已经审核了ECMA 335,我只找到了对该.export关键字的引用,该关键字看起来很有前景但文档很少.关于在C#中执行此操作,我在StackOverflow上发现了类似的问题.然而,到目前为止,这些都没有带给我任何有用的东西.
底线是:我有一个CIL DLL,我想从本机C++应用程序调用它的一些静态方法.
我想知道字段固定是如何用.Net的IL语言表达的,所以我看了一下示例代码:
struct S
{
public fixed int buf[8];
}
S s = default(S);
public void MyMethod() {
fixed (int* ptr = s.buf){
*ptr = 2;
}
}
Run Code Online (Sandbox Code Playgroud)
这会生成IL:
.method private hidebysig instance void MyMethod () cil managed
{
// Method begins at RVA 0x2050
// Code size 25 (0x19)
.maxstack 2
.locals init (
[0] int32& pinned
)
IL_0000: ldarg.0 // Load argument 0 onto the stack
IL_0001: ldflda valuetype C/S C::s // Push the address of field of object …Run Code Online (Sandbox Code Playgroud)