【发布时间】:2015-12-01 12:41:15
【问题描述】:
每当我尝试通过 Visual Studio 在 C# 中引用我自己的 DLL 时,它都会告诉我它无法引用 DLL,因为它不是 COM 库。
我在互联网上四处搜索以找到解决方案,但没有明确的答案或真正的帮助。这是一个相当“简单”的 DLL,它从指纹扫描仪捕获原始图片数据。在我尝试将其转换为 DLL 之前,我已经测试过 C++ 代码可以正常工作,你知道的。
我按照微软关于如何制作 DLL 的指南进行操作,结果如下:
- JTBioCaptureFuncsDll.h
- JTBioCaptureFuncsDll.cpp
- JTBioCapture.cpp
JTBioCaptureFuncsDll.h
#ifdef JTBIOCAPTUREFUNCSDLL_EXPORTS
#define JTBIOCAPTUREFUNCSDLL_API __declspec(dllexport)
#else
#define JTBIOCAPTUREFUNCSDLL_API __declspec(dllimport)
#endif
using byte = unsigned char*;
struct BioCaptureSample {
INT32 Width;
INT32 Height;
INT32 PixelDepth;
byte Buffer;
};
JTBioCaptureFuncsDll.cpp
// JTBioCapture.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
namespace JTBioCapture
{
using byte = unsigned char*;
class JTBioCapture
{
public:
// Returns a Struct with Information Regarding the Fingerprint Sample
static JTBIOCAPTUREFUNCSDLL_API BioCaptureSample CaptureSample();
};
}
JTBioCapture.cpp
/*
* Courtesy of WinBio God Satish Agrawal on Stackoverflow
*/
BioCaptureSample CaptureSample()
{
HRESULT hr = S_OK;
WINBIO_SESSION_HANDLE sessionHandle = NULL;
WINBIO_UNIT_ID unitId = 0;
WINBIO_REJECT_DETAIL rejectDetail = 0;
PWINBIO_BIR sample = NULL;
SIZE_T sampleSize = 0;
// Connect to the system pool.
hr = WinBioOpenSession(
WINBIO_TYPE_FINGERPRINT, // Service provider
WINBIO_POOL_SYSTEM, // Pool type
WINBIO_FLAG_RAW, // Access: Capture raw data
NULL, // Array of biometric unit IDs
0, // Count of biometric unit IDs
WINBIO_DB_DEFAULT, // Default database
&sessionHandle // [out] Session handle
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioOpenSession failed. hr = 0x%x\n", hr);
goto e_Exit;
}
// Capture a biometric sample.
wprintf_s(L"\n Calling WinBioCaptureSample - Swipe sensor...\n");
hr = WinBioCaptureSample(
sessionHandle,
WINBIO_NO_PURPOSE_AVAILABLE,
WINBIO_DATA_FLAG_RAW,
&unitId,
&sample,
&sampleSize,
&rejectDetail
);
if (FAILED(hr))
{
if (hr == WINBIO_E_BAD_CAPTURE)
{
wprintf_s(L"\n Bad capture; reason: %d\n", rejectDetail);
}
else
{
wprintf_s(L"\n WinBioCaptureSample failed. hr = 0x%x\n", hr);
}
goto e_Exit;
}
wprintf_s(L"\n Swipe processed - Unit ID: %d\n", unitId);
wprintf_s(L"\n Captured %d bytes.\n", sampleSize);
// Courtesy of Art "Messiah" Baker at Microsoft
PWINBIO_BIR_HEADER BirHeader = (PWINBIO_BIR_HEADER)(((PBYTE)sample) + sample->HeaderBlock.Offset);
PWINBIO_BDB_ANSI_381_HEADER AnsiBdbHeader = (PWINBIO_BDB_ANSI_381_HEADER)(((PBYTE)sample) + sample->StandardDataBlock.Offset);
PWINBIO_BDB_ANSI_381_RECORD AnsiBdbRecord = (PWINBIO_BDB_ANSI_381_RECORD)(((PBYTE)AnsiBdbHeader) + sizeof(WINBIO_BDB_ANSI_381_HEADER));
PBYTE firstPixel = (PBYTE)((PBYTE)AnsiBdbRecord) + sizeof(WINBIO_BDB_ANSI_381_RECORD);
int width = AnsiBdbRecord->HorizontalLineLength;
int height = AnsiBdbRecord->VerticalLineLength;
wprintf_s(L"\n ID: %d\n", AnsiBdbHeader->ProductId.Owner);
wprintf_s(L"\n Width: %d\n", AnsiBdbRecord->HorizontalLineLength);
wprintf_s(L"\n Height: %d\n", AnsiBdbRecord->VerticalLineLength);
BioCaptureSample returnSample;
byte byteBuffer;
for (int i = 0; i < AnsiBdbRecord->BlockLength; i++) {
byteBuffer[i] = firstPixel[i];
}
returnSample.Buffer = byteBuffer;
returnSample.Height = height;
returnSample.Width = width;
returnSample.PixelDepth = AnsiBdbHeader->PixelDepth;
/*
* NOTE: (width / 3) is necessary because we ask for a 24-bit BMP but is only provided
* a greyscale image which is 8-bit. So we have to cut the bytes by a factor of 3.
*/
// Commented out as we only need the Byte buffer. Comment it back in should you need to save a BMP of the fingerprint.
// bool b = SaveBMP(firstPixel, (width / 3), height, AnsiBdbRecord->BlockLength, L"C:\\Users\\smf\\Desktop\\fingerprint.bmp");
// wprintf_s(L"\n Success: %d\n", b);
e_Exit:
if (sample != NULL)
{
WinBioFree(sample);
sample = NULL;
}
if (sessionHandle != NULL)
{
WinBioCloseSession(sessionHandle);
sessionHandle = NULL;
}
wprintf_s(L"\n Press any key to exit...");
_getch();
return returnSample;
}
这个想法是在 C# 中调用“CaptureSample()”,然后代码尝试捕获指纹扫描。当它进行扫描时,应该将一个结构返回给它可以使用的 C#,并持有:
- 字节缓冲区
- 图像高度
- 图像宽度
- 图像像素深度
但是当我尝试在我的 C# 项目中引用 DLL 时,我收到以下错误:
我也尝试使用TlbImp.exe 工具制作DLL,但无济于事。它告诉我 DLL 不是有效的类型库。
所以我在这里有点迷路了。我是 C++ 的新手,所以制作 Interop/COM 组件不是我以前做过的事情,也不是制作用于 C# 的 DLL。
【问题讨论】:
-
您需要使用 DllImport。非托管 (c++) dll 不能直接添加到 .net 项目。请参阅this 答案。
-
希望这个线程对stackoverflow.com/a/12639732/3583859 有所帮助,正如 Farhan 提到的,是的,在非托管环境中您需要使用 dllImport。
-
您需要使用 P/Invoke、构建 C++/CLI 包装器或将 C++ dll 构建为 COM。只有最后两个可以添加dll作为参考。
-
你让它工作了吗?如果你(宽度/ 3)它会生成缩小的图像。你解决了这个问题吗?请上传您的代码