作者ab710912 (Leanne)
看板C_Sharp
标题[问题] 关於引用C++ dll的变数类别
时间Mon Nov 29 11:50:49 2021
工作上收到一份dll
他给的文件方法是
SnmpStatus(int& DeviceStatus,int& PrinterStatus,char* PrinterError);
所以我采用
[DllImport("MPrinterSnmp.dll", EntryPoint = "SnmpStatus", CallingConvention
= CallingConvention.StdCall,CharSet =CharSet.Unicode)]
public static extern int SnmpStatus(out int DeviceStatus, out int
PrinterStatus,ref StringBuilder PrinterError);
可是一呼叫 程式就直接结束工作,连例外都没跳出
曾经有一次 把 StringBuilder改成Char有成功取得值一次
但是後来再试就一样直接跳掉
StringBuilder 改试过 String、byte[2]、String[2]、IntPtr、char、char[2]
都是直接跳掉
另外 他有附他的.h给我 里面的方法是
extern "C" __declspec(dllexport) int __stdcall SnmpStatus(int
&DeviceStatus,int &PrinterStatus,char *PrinterError);
*和&的位置和文件的位置有些微不一样 不知道有没有差别
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 60.248.154.118 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_Sharp/M.1638157851.A.621.html
1F:→ ssccg: 要用IntPtr,然後用Marshal.PtrToStringAnsi 11/29 13:02
IntPtr我试过 至少要先不会跳掉才有机会可以去转String吧?
※ 编辑: ab710912 (60.248.154.118 台湾), 11/29/2021 13:15:47
2F:→ ssccg: 这函式看起来是传char*(=IntPtr)进去,然後里面会把结果直 11/30 11:23
3F:→ ssccg: 接写到这个pointer的位置,你传进去的IntPtr哪来的? 11/30 11:27
4F:→ ssccg: Marshal.AllocHGlobal? 11/30 11:28
5F:推 s4300026: 我觉得是 char 跟 wchar 的问题。 String^ 是wchar. 11/30 12:28
6F:→ s4300026: 话说为什麽不自己写wrapper class,要用dllimport 11/30 12:28
7F:推 s4300026: 你char会在dll里面改变大小吗? 你怎麽保证不会overflow 11/30 12:29
8F:推 testPtt: unsafe 12/01 08:43
9F:推 s4300026: 话说好奇问一下,undafe的native pointer要怎麽new 和de 12/01 12:05
10F:→ s4300026: lete? 12/01 12:05
11F:→ testPtt: NativeMemory Class 12/01 13:38
12F:推 Litfal: 楼上是指IntPtr?通常是C library开api负责new和del吧 12/01 13:51
13F:→ Litfal: 然後C++的&不一定是out,用ref比较一致,虽然我觉得在api 12/01 13:54
14F:→ Litfal: 里面用&还颇……特殊的,大部分都会用一致性更高的* 12/01 13:54
15F:推 Litfal: 你在丢StringBuilder和char[ ]时不需要ref,C#丢物件预设 12/01 13:58
16F:→ Litfal: 就是传址了 12/01 13:58
17F:→ Litfal: StringBuilder要初始空间给他用,char[]和byte[]也是一样 12/01 14:00
18F:→ Litfal: 。开大一点,拜托,能跑再来考虑怎麽省 12/01 14:00
19F:推 Litfal: 他api用char,应该不会是Unicode,注意一下 12/01 14:06
20F:推 s4300026: 回Litfal, 我是指*或是**,因为unsafe可以使用native pt 12/01 15:47
21F:→ s4300026: r,但c#并没有对应的new delete关键字。 12/01 15:47
22F:推 s4300026: 确实我後来是在api中多宣告了new/delete的方法来解决。 12/01 15:51
23F:→ s4300026: 只是我在想,有没有在外部new好再丢入dll内的方式。 12/01 15:51
25F:→ s4300026: 我目前是这样写,不是走dllimport的方式,但对於 & 和 % 12/01 16:05
26F:→ s4300026: 那里不知道要怎麽转会更好。 12/01 16:05
27F:推 Litfal: 有这种需求我是用Marshal.AllocHGlobal啦,不用fixed或St 12/01 16:33
28F:→ Litfal: ructureToPtr,我是用在图像处理,C#端也有一些处理函数 12/01 16:33
29F:→ Litfal: ,对速度斤斤计较才这样搞 12/01 16:33
感谢各位那麽认真的讨论...昨天我有尝试成功了
原因只是改成X86建置降为.net2.0就可以过了
改成这样後无论类型带甚麽都可以过 只是输出值不一定有值或不一定对就是了
最後还是用了char
public static extern int SnmpStatus(out int DeviceStatus, out int
PrinterStatus, ref char PrinterError);
这样感觉出来跟我要的结果比较像
感谢各位
※ 编辑: ab710912 (60.248.154.118 台湾), 12/01/2021 17:22:07
※ 编辑: ab710912 (60.248.154.118 台湾), 12/01/2021 17:22:57