• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 402
  • Last Modified:

Adding a DLL to my project


I have a DLL I'm trying to incorporate into my project, without luck.  The application used to make the DLL was MFC, I believe.  From Solution Explorer, I select to Add a Reference, switch to the COM page, and browse to select the DLL.  But when I press OK I get a failure messagebox, that it's not a valid assmebly of COM component.  I thought all DLLs were COM components.

I have the C++ header file by the same name as the DLL.

Any suggestions?

  • 7
  • 7
  • 2
  • +1
3 Solutions
MFC dll can export classes and functions. If it exports functions, you can call them using PInvoke. If it exports classes, it cannot be called directly from C#, and it is necessary to write wrapper Dll. In both cases, MFC Dll cannot be added as reference to C# project.
Post Dll interface h-file to see what happens.
ba272Author Commented:
#ifndef AIDAPI_INC
#define AIDAPI_INC

// Async ID transfer defines
#define ASYNCTMRID (WM_USER + 1)
#define EOTCHR 0xAA
#define ESCCHR 0xBB

/* Returned from Base...
  '0' The command was successful.
  '1' The <ATT> character was issued before completion of the command (abort)
  '2' Bad Base Command (out of range or out of context as in Transfer Mode '1' and using Get ID Table cmd)
  '3' Failed CheckSum on transmission from the PC to the Base [not possible in LT product]
  '4' Failed Checksum on return from Badge to Base [not possible in LT product]
  '5' Timeout on transfer from PC to Base [not possible in LT product]
  '6' Timeout on transfer from Badge to Base (retries exhausted) [not possible in LT product]
  '7' Bit Error detected on transfer from Badge to Base [not possible in LT product]
  '8' Base EEProm write error
  '9' Network Busy  [not possible in LT product]

/* Base Commands  -  AirID and/or LT
  'a' Get Base Version      AID/LT
  'b' Set Cycle Count       AID
  'c' Get Cycle Count       AID
  'd' Set Attenuation       AID/LT
  'e' Get Attenuation       AID/LT
  'h' Set ID Timeout        LT
  'i' Get ID Timeout        LT
  'j' Get ID Table          LT
  'k' Set Transfer Mode     LT
  'l' Get Transfer Mode     LT
/* Badge Commands  -  AirID Only
  0 Get Mobile Version
  1 Set Password
  2 Get Password
  3 Address Probe
  4 Set Passcode
  5 Get Passcode
  6 Initialize Parameters
  7 Set Address
  8 Get Address

class AidAPI
// methods
  // construction / destruction
  virtual ~AidAPI();

  // implementation methods for Base Communications
  WORD GetBaseVersion( char *ver ); //'a' Get Base Version
  WORD SetBaseRetryCnt( WORD cnt ); //'b' Set Cycle Count
  WORD GetBaseRetryCnt( WORD *cnt ); //'c' Get Cycle Count
  WORD SetBaseRxAtten( WORD atten ); //'d' Set Attenuation
  WORD GetBaseRxAtten( WORD *atten ); //'e' Get Attenuation
  WORD SetIDTimeout( WORD to ); //'h' Set ID Timeout
  WORD GetIDTimeout( WORD *to ); //'i' Get ID Timeout
  WORD GetActiveIDs( WORD seed, DWORD *pdwtbl, WORD *cnt, WORD *auth ); //'j' Get ID Table
  WORD SetIDXfrMode( WORD mode, WORD seed ); //'k' Set Transfer Mode
  WORD GetIDXfrMode( WORD *mode ); //'l' Get Transfer Mode

  void InitAsyncProt( void );  // initialize Async xfr mode variables after each msg
  WORD PutAsyncXfrChr( WORD c ); // feed the Async xfr mode protocol received chrs
  WORD GetAsyncXfrData( DWORD *id, WORD *flags, WORD *key ); // call when PutAsyncXfrChr return TRUE

  // implementation methods for Badge Communications

  WORD GetBadgeVersion( DWORD Addr, char *ver ); //0      Get Mobile Version
  WORD SetBadgePassword( DWORD Addr, WORD bank, DWORD Pcd, char *pPwd ); //1 Set Password
  WORD GetBadgePassword( DWORD Addr, WORD bank, DWORD Pcd, char *pPwd, char *garbage ); //2 Get Password
  WORD ProbeBadge( DWORD Addr ); //3 Address Probe
  WORD SetBadgePasscode( DWORD Addr, WORD bank, DWORD newPcd ); //4 Set Passcode
  WORD GetBadgePasscode( DWORD Addr, WORD bank, char *pPwd, DWORD *pPcd ); //5 Get Passcode
  WORD InitBadge( DWORD Addr, WORD bank ); //6 Initialize Parameters
  WORD SetBadgeAddress( DWORD Addr ); //7 Set Address
  WORD GetBadgeAddress( DWORD Addr, DWORD *pRetAddr ); //8 Get Address (Probe w/ Addr return)

  virtual WORD CycleBaseCmd( BYTE *txbuf, WORD txcnt, BYTE *rxbuf, WORD rxcnt );
  virtual WORD CycleBadgeCmd( BYTE *txbuf, WORD txcnt, BYTE *rxbuf, WORD rxcnt );
  WORD WakeBase( void );
  WORD TxCmd( BYTE *buf, int cnt );
  WORD RxRsp( BYTE *buf, int cnt );
  int Authenticate(
                   WORD TxChlng,
                   WORD RxRsp,
                   BYTE *pTmrTbl,
                   int ntimers
  BYTE CalcChkSum( BYTE *pbuf, WORD cnt );
  BYTE rrc( BYTE *pbuf, BYTE carry, BYTE bytecnt );
  void Crypt(
             BYTE *Address,
             BYTE *ComKey,
             BYTE *BankKey,
             BYTE *inbuf,
             BYTE cnt

  // pure virtual, user must fill these in
  // serial communications - Synchronous Mode Only!
  virtual WORD TxChr( WORD c ) = 0;
  virtual WORD RxChr( void ) = 0;

// data
  BYTE TxBuf[64];
  BYTE RxBuf[64];
  BYTE CmdData[32];
  // Async transfer mode data
  BYTE AsyncMsg[32];  // Async mode msg buf
  WORD bAsyncMsg;
  int AsyncMsgChrCnt;  // Async mode - running count of chars
  BYTE AsyncMsgChkSum;  // Async mode - checksum accumulator
  int bAsyncRxProtInEsc;  // Async mode - flags ESC char received



This class cannot be imported directly to C# project. You must write wrapper, one of two types:
1) C++ Dll which internally uses AidAPI class and exposes C-style API interface, which can be called by C# client using PINvoke.
2) C++/CLI Class Library which internally uses AidAPI class end exposes to C# client pure .NET interface.

To my opinion, second way is better.

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

ba272Author Commented:

I like option #2 as well.

Do I use the C++ Class Library choice?  That's the second template in VS 2003 for C++ .NET projects.

Is there an easy way expose the entire interface?  Or do I need to add the calls one at a time?

You need to create C++/CLI class library and add wrapper class to it. Inside of this class keep AidAPI member. For all AidAPI functions (or every function which is used by client) add function to wrapper class, translating native types to .NET types when necessary.
Other way is to write more functionality to C++/CLI class. In this case you don't need to wrap every AidAPI function. For example, some wrapper function makes number of calls to AidAPI providing single call to C# client.
Actually, I found that this is not so simple - C++/CLI project cannot read MFC Dll. I will make some tests and return to this thread.
actually you need to add an new dll between the mfc and the c++/cli
one made in vsc++ 7.0, make a wrapper there, then use this wrapper in the c++/cli dll where you can expose the classes to .net

to be more clear. the dll i was talking about should be a mfc dll but made with 7.0
OK, this is working. C++/CLI client can work with MFC Dll. You can continue in this direction.
ba272Author Commented:
ba272Author Commented:
When I created a Class Library (.NET) project, then attempted to add the DLL, I got an error when adding a reference to the DLL.  Any ideas what the problem is?
ba272Author Commented:
I get the exact error when I created a sample MFC Application and tried to add a reference to the same DLL.

"Add Reference: Error adding reference to the project"
You need to add .lib file to the list of external dependencies for linker. Project - Properties - Linker - Additional Dependencies. Type here name of .lib file. Then add #include line and use this class.
You need to use PINVOKE
ba272Author Commented:

I don't have a .lib file.  But I do have various dll's from which to choose.  How about the one with this header?  It appear to be more focused on what I want.  I do not have a .lib file for any of them though.

Do I need an older version of Visual C++ in order to create the C++/CLI client you'd talked about, as Agarici suggests?





typedef enum eErrCode {
} teErrCode;

// CDECL type call
typedef long (*GETPCPROXID)( DWORD, PSTR );
// PASCAL type call

//long GetPCProxID( DWORD dwOptions, char *szRetBuf );
  DWORD dwOptions
    1st (Low) Byte
      Low 4 bits is the Comm Port - 1 thru 15 (Zero will force a search from Comm1-4
      Upper 4 bits should be zero (undefined) - someday could specify USB options
    2nd Byte
      Low 4 bits is the Max Comm Port connect time in seconds - 0 thru 15
          On NT, the Comm I/O takes a while to come up.
          It's seldom ready when the GINA entry points are accessed.
          Set this to 15 then back off if you like.
      Upper 4 bits should be zero (undefined)
    3rd Byte
      Low bit:0 - '0'= no debug dialogs, '1'= use debug dialogs
      Others are undefined as yet.
    4th (High) Byte
      Undefined as yet.

  char *szRetBuf:
    Pointer to a buffer of minimum size IDSTRRETBUF_SZ
    which includes the space for the terminating NULL
    (the strlen is at most IDSTRRETBUF_SZ - 1).
    The string ID returned has little to do with the ID
    printed on most cards.  You may want to use a 'HASH'
    of this string to narrow a database search.  The ID
    from the internal reader may be up to 64 bits long
    and it is too difficult to deal with a 64 bit unsigned
    integer so we treat it as two 32 bit DWORDS.  The ID
    includes the 'Facility Code' data along with the ID
    within the particular FacCode.  The code below demonstrates
    how the String ID is constructed from two DWORDs.

  Returns: One of the 'eErrCode's listed above,
           eErrCode_None (0) is good.

  Remarks: The string buffer is NULL terminated before
           any processing starts (unless the pointer is NULL).
           So, given a non-NULL pointer, the buffer will be
           initialized to a zero-length string regardless
           of the overall outcome.
    The interface call is a 'cdecl' not a PASCAL type!!!
    i.e. don't use APIENTRY declaration or anything else that
    resolves to a PASCAL type call.

// max string = "42949672954294967295" = 0xFFFFFFFF : 0xFFFFFFFF
//            = 20 characters of ID + 1 NULL char = 21 char buf needed
BOOL IDExToStrID( DWORD dwId, DWORD dwIdEx, char *szIdStrBuf )
  if( NULL == szIdStrBuf ) return FALSE;
  if( dwIdEx )
    sprintf( szIdStrBuf, "%lu%010lu", dwIdEx, dwId );
    sprintf( szIdStrBuf, "%lu", dwId );
  return TRUE;


#endif //#ifndef RFIDREAD_INC
To work with Dll which exports class, you need .lib file. If Dll exports functions, you can use PInvoke. IDExToStrID function can be called using PINvoke, but why do you need it?
I hope you have an idea what functions do you need to used from this SDK. h-file must contain all of them. Currently, you posted AidAPI class, but you don't have .lib file, so this class cannot be used in .NET and in any previous versions. You posted also h-file which doesn't contain any useful stuff. This is not enough,  must be something else.
ba272Author Commented:
ok.  I'll keep looking.

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 7
  • 7
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now