我需要从c#调用外部dll.这是标题定义:
enum WatchMode {
WATCH_MODE_SYSTEM = 0,
WATCH_MODE_APPLICATION = 1 };
LONG ADS_API WDT_GetMode ( LONG i_hHandle, WatchMode * o_pWatchMode );
Run Code Online (Sandbox Code Playgroud)
我在C#中添加了枚举和调用:
public enum WatchMode
{
WATCH_MODE_SYSTEM = 0,
WATCH_MODE_APPLICATION = 1
}
[DllImport("AdsWatchdog.dll")]
internal static extern long WDT_GetMode(long hHandle, ref WatchMode watchmode);
Run Code Online (Sandbox Code Playgroud)
这会生成AccessViolationException.我知道dll正在"工作",因为我还添加了一个调用GetHandle,返回hHandle上面提到的.我试图将参数更改为int(ref int watchmode)但得到相同的错误.没有人知道我怎么能拨打上述电话吗?
我试图通过传递标志来通过子进程继承桌面的PInvoke CreateDesktop.声明如下:
[DllImport("user32", EntryPoint = "CreateDesktopW", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CreateDesktop(string lpszDesktop, IntPtr lpszDevice, IntPtr pDevmode, int dwFlags,
int dwDesiredAccess, [MarshalAs(UnmanagedType.LPStruct)] SECURITY_ATTRIBUTES lpsa);
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
Run Code Online (Sandbox Code Playgroud)
我用它如下:
Win32.SECURITY_ATTRIBUTES sa = new Win32.SECURITY_ATTRIBUTES();
sa.nLength = Marshal.SizeOf(sa);
sa.bInheritHandle = 1;
testDesktopHandle = Win32.CreateDesktop(name, IntPtr.Zero, IntPtr.Zero, 0, Win32.GENERIC_ALL, sa);
Run Code Online (Sandbox Code Playgroud)
不幸的是,它不起作用,我收到以下错误:
System.Runtime.InteropServices.MarshalDirectiveException: Cannot marshal 'parameter #6': Invalid managed/unmanaged type combination (this value type must be paired …Run Code Online (Sandbox Code Playgroud) 尝试整理范围并避免可能多次调用RegisterWindowMessage.
目前有一个类使用以下成员一次
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int RegisterWindowMessage(string lpString);
private int m_message = RegisterWindowMessage("MY_MSG");
Run Code Online (Sandbox Code Playgroud)
由于我们只有一个实例,这似乎没问题,但认为使用它会更整洁.根据我的基本C#理解,这应该调用RegisterWindowMessage并将结果分配给int并且不允许它更改.
private const int message = RegisterWindowMessage("MY_MSG");
Run Code Online (Sandbox Code Playgroud)
但试图这样做会导致a
error CS0133: The expression being assigned to 'someclass.messageEvent' must be constant
Run Code Online (Sandbox Code Playgroud)
所以现在我很困惑,这是否意味着函数被分配并且每次调用之前都m_message被调用过,是否还有其他缺失?
以下.net到本机C代码不起作用,任何想法
extern "C" {
TRADITIONALDLL_API int TestStrRef( __inout char* c) {
int rc = strlen(c);
std::cout << "the input to TestStrRef is: >>" << c << "<<" ;
c = "This is from the C code ";
return rc;
}
}
[DllImport("MyDll.dll", SetLastError = true)]
static extern int TestStrRef([MarshalAs(UnmanagedType.LPStr)] ref string s);
String abc = "InOut string";
TestStrRef(ref abc);
Run Code Online (Sandbox Code Playgroud)
此时Console.WriteLine(abc)应该打印"这是来自C代码"但是没有,任何关于什么错误的想法?
仅供参考 - 我有另一个不使用ref类型字符串的测试函数,它工作得很好
我的问题是,我在DLL中有一些函数,其中一些函数是例如:
#include <string>
using namespace std;
extern "C" __declspec(dllexport) string __cdecl encryption(string s)
{
return s;
}
Run Code Online (Sandbox Code Playgroud)
每当我尝试从C#调用此函数时,以下是使用的代码:
[DllImport("Packer.dll", EntryPoint = "encryption")]
static extern string encryption(string s);
Run Code Online (Sandbox Code Playgroud)
我收到一个错误:调用PInvoke函数'Packer'使堆栈失衡.这很可能是因为托管PInvoke签名与非托管目标签名不匹配.检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配.
我猜我得到这个错误,因为我没有正确的功能声明任何人都可以指导我如何解决这个问题,提前谢谢
我想知道哪个更好地将C++代码转换为C#或从C#app中进行Pinvoking
这在性能和内存等方面会更好
我在VS中创建了新的Win32项目,并为此目的选择了动态库(*.dll).
我在主文件中定义了一些导出函数:
__declspec(dllexport)
int TestCall(void)
{
int value = 4 / 2;
std::cout << typeid(value).name() << std::endl;
return value;
}
__declspec(dllexport)
void SwapMe(int *first, int *second)
{
int tmp = *first;
*first = *second;
*second = tmp;
}
Run Code Online (Sandbox Code Playgroud)
当我看到dumpin/exports时,我得到了:
ordinal hint RVA name
1 0 00001010 ?SwapMe@@YAXPEAH0@Z
2 1 00001270 ?TestCall@@YAHXZ
Run Code Online (Sandbox Code Playgroud)
我正在调用C#这样的版本:
[DllImport(@"lib1.dll", EntryPoint = "?TestCall@@YAHXZ",
CallingConvention = CallingConvention.Cdecl)]
static extern int TestCall();
Run Code Online (Sandbox Code Playgroud)
这不是使用导出方法的正确形式.我在C++ DLL项目中为导出方法生成这样的名称失败了吗?
有:
[DllImport("OpenAL32.dll")]
static extern void alcOpenDevice(char*[] devicename);
Run Code Online (Sandbox Code Playgroud)
想把这个名字发送给像smth那样的函数:
char[] data = "Hello!".ToCharArray();
char*[] txt = &data;
Run Code Online (Sandbox Code Playgroud)
但得到错误:
无法隐式转换
char[] *为char * []
(有趣的错误,因为C#编译器拒绝char[] *在/ unsafe模式中定义:))
不能获取地址,获取大小,或声明指向托管类型的指针(
char[])
PS
何时char成为管理?这是一个结构,不是吗?
public struct Char : IComparable, IConvertible, IComparable<char>, IEquatable<char>
Run Code Online (Sandbox Code Playgroud)
虽然编译器显示有关声明指向托管类型(char[])的指针的信息.我只能建议当类型是一个数组时,CLR可能会像管理类型一样呈现它,但听起来非常疯狂.
在我正在研究的项目中,我偶然发现了这个问题:
我想创建一个类"ApiID"的实例.我从Reflector获得了代码,因为你可以看到.dll(不是我的Project)导入来自ummanaged代码,我无权访问.
[StructLayout(LayoutKind.Sequential, Size=0x10), CLSCompliant(false), NativeCppClass, DebugInfoInPDB, MiscellaneousBits(0x40)]
public struct ApiId
{
private long <alignment member>;
public static unsafe void <MarshalCopy>(ApiId* idPtr1, ApiId* idPtr2)
{
ApiId.{ctor}(idPtr1, (ApiId modopt(IsConst)* modopt(IsImplicitlyDereferenced)) idPtr2);
}
public static unsafe void <MarshalDestroy>(ApiId* idPtr1)
{
ApiId.{dtor}(idPtr1);
}
}
Run Code Online (Sandbox Code Playgroud)
我的C#-Code看起来像这样:
var _apiId = new ApiId();
long vlue = 0x0000000041403070;
typeof(ApiId).GetField("<alignment member>", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(_apiId, vlue);
Run Code Online (Sandbox Code Playgroud)
该代码成功运行,但是Field不会改变并保持0 ...我做错了什么?问候
我一直面临的一个问题是.NET Framework类库的实现.
我知道一些原始实现的方法:
例如 :
MessageBox.Show("...");
Run Code Online (Sandbox Code Playgroud)
据我所知,这个方法必须使用P/Invoke来调用Win32 API.
但是像这样:
System.Convert.ToInt32(mystr);
Run Code Online (Sandbox Code Playgroud)
我实际上不知道它是如何工作的,因为在纯C#中不可能在int和string之间进行转换.(你可以在不使用该方法的情况下做同样的事情吗?实际上我不知道).
最后,如果您知道答案,请在第二个例子中为我澄清这些概念.