C#中DLL无法工作

4
每当我试图通过Visual Studio在C#中引用自己的DLL时,它告诉我无法引用该DLL,因为它不是COM库。
我在互联网上搜索了解决方案,但没有明确的答案或任何帮助。这是一个相当“简单”的DLL,它捕获指纹扫描仪的原始图片数据。在我将其制作成DLL之前,我已经测试过C++代码完美运行。
我遵循了Microsoft的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#,以便它使用,其中包含:
  • Byte Buffer
  • Image Height
  • Image Width
  • Image Pixeldepth
但是,当我尝试在C#项目中引用DLL时,出现以下错误:

Error

我还尝试使用“TlbImp.exe”工具制作DLL,但无济于事。它告诉我该DLL不是有效的类型库。
所以我有点迷茫。我对C++很陌生,因此创建Interop/COM组件不是我以前做过的事情,也没有为在C#中使用而制作DLL的经验。

你需要使用DllImport。一个非托管(c++)dll不能直接添加到.net项目中。请参考这个答案。 - Fᴀʀʜᴀɴ Aɴᴀᴍ
希望这个线程可以帮到你,正如Farhan所提到的,在非托管环境中,你需要使用dllImport。 - Vijay Kumbhoje
1
你需要使用P/Invoke,构建一个C++/CLI包装器或将C++ dll构建为COM。只有后两种方法才能将dll添加为引用。 - crashmstr
你解决了这个问题吗?如果你将宽度除以3,它会生成缩小的图像。请上传你的代码。 - kakopappa
1个回答

1

好的,谢谢你提供的信息!我会尝试去查看 :) - OmniOwl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接