这个C++的DLL怎么在C#中声明?

bys_home 2007-10-04 10:40:34
--UDT中发送与收取文件的
typedef __int64 int64_t;
#ifdef UDT_EXPORTS
#define UDT_API __declspec(dllexport)
#else
#define UDT_API __declspec(dllimport)
#endif

UDT_API int64_t sendfile(UDTSOCKET u, std::ifstream& ifs, const int64_t& offset, const int64_t& size, const int& block = 366000);

UDT_API int64_t recvfile(UDTSOCKET u, std::ofstream& ofs, const int64_t& offset, const int64_t& size, const int& block = 7320000);
...全文
208 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
htz92127 2007-10-05
  • 打赏
  • 举报
回复
不用特意写其他的声明吧。只要声明函数时声明为public就可以了!在c#是可以用的,不过在c++里能不能调用我就不知道了,应该也可以吧
soaringbird 2007-10-05
  • 打赏
  • 举报
回复
ifstream和ofstream肯定是不能用的,至于那个UDTSOCKET,还要看他的具体定义,如果是一个结构,可以翻译一下。
建议你把这几个函数重新封装一下
ice_frank 2007-10-04
  • 打赏
  • 举报
回复
UP
refyl 2007-10-04
  • 打赏
  • 举报
回复
我们也应该说明这里我们的重点在于声明公共的,导出的DLL函数。默认情况下,在DLL中的函数是私有的。UNIX程序员可能注意到与在UNIX共享库中函数处理方面的区别,在UNIX共享库中所有的函数都是公有的。在所有版本的Windows中,除非函数是导出的,否则DLL的函数是私有的。只有导出的函数对外部环境是可见的,在这里外部环境是指.NET精简框架应用程序的托管代码和.NET精简框架的DLL。

理解函数声明的最好的方法是研究一个例子。下面的函数,ShowInt32ByVal,出自于ShowParam的例子。它显示了在DLL中声明一个导出的C++函数所需的所有的元素。

extern "C" __declspec(dllexport)



void WINAPI ShowInt32ByVal(LONG val)

{

WCHAR wch[128];

wsprintf(wch, L"ShowInt32ByVal = %d", val);

MessageBoxW(NULL, wch, pLibName, 0);

}

第一行的extern "C"部分告诉C++编译器关闭name mangling(有时叫做name decorating),这个属性可以允许你在C++程序中重载函数名。当编写一段由其他C++代码调用的C++代码时,name mangling是有帮助的,但它妨碍了编写能够从托管代码调用的C++代码。例如,ShowInt32ByVal函数在去掉外部(extern)声明时,被重命名为?ShowInt32ByVal@@YAXJ@Z(这也是被称作name mangling的原因)。

第一行中的__declspec(dllexport)部分告诉C++编译器来导出一个函数。这是必须的,因为在默认情况下,所有的函数都是私有隐藏的。导出一个函数使得这个函数可见,进而可以从外部DLL调用。

WINAPI声明也是必需的。但是它隐藏了一个重要的元素,调用约定(calling convention)。调用约定的重要性在于如果你使用了一个错误的声明,会保证函数调用失败。这是一个失败的经验,它尽力指出为什么函数失败的原因,只为了发现你正在使用的错误的调用约定。

调用约定描述了编译器在函数之间如何传递参数和函数调用后谁来清理堆栈。在老的Windows代码中,你有时会看到PASCAL关键字作为在16位Windows系统中的一个调用习惯的提示。(一些人认为这意味着Microsoft已经在实现Windows时使用了Pascal-----这是一个旧的观点,因为Microsoft的主要竞争对手Borland有更好的Pascal编译器。)两个对于Win32程序员来说很有趣的调用约定是声明CDECL和STDCALL(对编译器的本地的__cdecl和__stdcall声明的简便别名)。

这是桌面和设备的分歧所在。对于Win32函数在桌面下的标准的调用约定是STDCALL调用约定,而在Win CE下标准调用约定是CDECL。为了使得创建的Win32代码在这两种环境间是可移植的,Microsoft提供了WINAPI调用约定声明。在桌面下,这被定义为STDCALL,在Windows CE下这个声明被定义为CDECL。

代码清单4.5包括ShowParam.cpp的源代码,在CallWin32例子中DLL被调用的过程显示在本章前面的部分。

代码清单4.5 演示通过传引用和传值调用的显示值的ShowParam.cpp代码

// ShowParam.cpp – 显示传值和传引用的各种.NET数据类型

//

//文件位置:\YaoDurant\CPP\PlatformInvoke\ShowParam

//

// Code from:

// _.NET Compact Framework Programming with Visual Basic .NET_

// Authored by Paul Yao and David Durant.





#include "stdafx.h"

#include "showparam.h"



LPWSTR pLibName = L"ShowParam - Win32 DLL";



BOOL APIENTRY



DllMain(HANDLE hModule,

DWORD ul_reason_for_call,

LPVOID lpReserved)

{

return TRUE;

}



//

// ShowBooleanByVal - Display Boolean value passed by value.

// ShowBooleanByVal – 显示传值的Boolean值

//



extern "C" __declspec(dllexport)

void WINAPI ShowBooleanByVal(BYTE val)

{

WCHAR wch[128];

wsprintf(wch, L"BoolByVal = %d", val);

MessageBoxW(NULL, wch, pLibName, 0);

}



//

// ShowBooleanByRef - Display Boolean value passed by reference.

// ShowBooleanByRef – 显示传引用的Boolean值

//



extern "C" __declspec(dllexport)



void WINAPI ShowBooleanByRef(BYTE * val)

{

WCHAR wch[128];

wsprintf(wch, L"BoolByRef = %d", *val);

MessageBoxW(NULL, wch, pLibName, 0);

}



//

// ShowByteByVal – 显示传值的Byte值。.

//

extern "C" __declspec(dllexport)

void WINAPI ShowByteByVal(BYTE val)

{

WCHAR wch[128];

wsprintf(wch, L"ShowByteByVal = %d", val);

MessageBoxW(NULL, wch, pLibName, 0);

}



//

// ShowByteByRef – 显示传引用的Byte值.

//



extern "C" __declspec(dllexport)



void WINAPI ShowByteByRef(BYTE * val)

{

WCHAR wch[128];

wsprintf(wch, L"ShowByteByRef = %d", *val);

MessageBoxW(NULL, wch, pLibName, 0);

}


bys_home 2007-10-04
  • 打赏
  • 举报
回复
也就是说没有办法来实现的了?不能转换成流样的东西,
UDTSocket是他的一个套接字,就像Socket差不多的东西,这里指的是handle
soaringbird 2007-10-04
  • 打赏
  • 举报
回复
这个没法在C#中声明,因为ifstream是C++类库中的东西,在C#中没有内存布局完全对应的东西。
真相重于对错 2007-10-04
  • 打赏
  • 举报
回复
UTDSOCEKET
是什么?
是否能否了解它确切的内存布局,可以则可以调用,否则不行
bys_home 2007-10-04
  • 打赏
  • 举报
回复
我想应该是std::ifstream这个的声明不对的吧,我改为BinaryReader也是同样出错。
bys_home 2007-10-04
  • 打赏
  • 举报
回复
不对的,这样声明会提示"尝试读取或写入受保护的内存。这通常指示其他内存已损坏"错误
lalac 2007-10-04
  • 打赏
  • 举报
回复
LZ给的信息不足的,不过可以写个原型,仅当参考。


public const int DEFAULT_IN_BLOCK = 366000;
public const int DEFAULT_OUT_BLOCK = 7320000;

[System.Runtime.InteropServices.DllImport("your dll name")]
public static extern Int64 sendfile(UDTSOCKET u, System.IO.Stream ifs, Int64 offset, Int64 size, int block);

[System.Runtime.InteropServices.DllImport("your dll name")]
public static extern Int64 sendfile(UDTSOCKET u, System.IO.Stream ifs, Int64 offset, Int64 size, int block);

[System.Runtime.InteropServices.StructLayout( System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct UDTSOCKET
{
// Add define here.
}
skyell 2007-10-04
  • 打赏
  • 举报
回复
楼上说的没明白

111,115

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧