Добавим функцию:
long GetClassObject(const WCHAR_T* wsName, IComponentBase** pInterface)
{
if(!*pInterface)
{
*pInterface= new Component;
return (long)*pInterface;
}
return 0;
}
В ней у нас используется тип IComponentBase, который нам необходимо описать. Для этого в файлах заголовках добавляем:
В него добавляем следующий код:
/*
* Warning!!!
* DO NOT ALTER THIS FILE!
*/
#ifndef __COMPONENT_BASE_H__
#define __COMPONENT_BASE_H__
#include "types.h"
////////////////////////////////////////////////////////////////////////////////
/**
* The given interface is intended for initialization and
* uninitialization of component and its adjustments
*/
/// Interface of component initialization.
class IInitDoneBase
{
public:
virtual ~IInitDoneBase() {}
/// Initializes component
/**
* @param disp - 1C:Enterpise interface
* @return the result of
*/
virtual bool ADDIN_API Init(void* disp) = 0;
/// Sets the memory manager
/*
* @param mem - pointer to memory manager interface.
* @return the result of
*/
virtual bool ADDIN_API setMemManager(void* mem) = 0;
/// Returns component version
/**
* @return - component version (2000 - version 2)
*/
virtual long ADDIN_API GetInfo() = 0;
/// Uninitializes component
/**
* Component here should release all consumed resources.
*/
virtual void ADDIN_API Done() = 0;
};
///////////////////////////////////////////////////////////////////////////
/**
* The given interface defines methods that are intented to be used by the Platform
*/
/// Interface describing extension of language.
class ILanguageExtenderBase
{
public:
virtual ~ILanguageExtenderBase(){}
/// Registers language extension
/**
* @param wsExtensionName - extension name
* @return the result of
*/
virtual bool ADDIN_API RegisterExtensionAs(WCHAR_T** wsExtensionName) = 0;
/// Returns number of component properties
/**
* @return number of properties
*/
virtual long ADDIN_API GetNProps() = 0;
/// Finds property by name
/**
* @param wsPropName - property name
* @return property index or -1, if it is not found
*/
virtual long ADDIN_API FindProp(const WCHAR_T* wsPropName) = 0;
/// Returns property name
/**
* @param lPropNum - property index (starting with 0)
* @param lPropAlias - 0 - international alias,
* 1 - russian alias. (International alias is required)
* @return proeprty name or 0 if it is not found
*/
virtual const WCHAR_T* ADDIN_API GetPropName(long lPropNum,
long lPropAlias) = 0;
/// Returns property value
/**
* @param lPropNum - property index (starting with 0)
* @param pvarPropVal - the pointer to a variable for property value
* @return the result of
*/
virtual bool ADDIN_API GetPropVal(const long lPropNum,
tVariant* pvarPropVal) = 0;
/// Sets the property value
/**
* @param lPropNum - property index (starting with 0)
* @param varPropVal - the pointer to a variable for property value
* @return the result of
*/
virtual bool ADDIN_API SetPropVal(const long lPropNum,
tVariant* varPropVal) = 0;
/// Is property readable?
/**
* @param lPropNum - property index (starting with 0)
* @return true if property is readable
*/
virtual bool ADDIN_API IsPropReadable(const long lPropNum) = 0;
/// Is property writable?
/**
* @param lPropNum - property index (starting with 0)
* @return true if property is writable
*/
virtual bool ADDIN_API IsPropWritable(const long lPropNum) = 0;
/// Returns number of component methods
/**
* @return number of component methods
*/
virtual long ADDIN_API GetNMethods() = 0;
/// Finds a method by name
/**
* @param wsMethodName - method name
* @return - method index
*/
virtual long ADDIN_API FindMethod(const WCHAR_T* wsMethodName) = 0;
/// Returns method name
/**
* @param lMethodNum - method index(starting with 0)
* @param lMethodAlias - 0 - international alias,
* 1 - russian alias. (International alias is required)
* @return method name or 0 if method is not found
*/
virtual const WCHAR_T* ADDIN_API GetMethodName(const long lMethodNum,
const long lMethodAlias) = 0;
/// Returns number of method parameters
/**
* @param lMethodNum - method index (starting with 0)
* @return number of parameters
*/
virtual long ADDIN_API GetNParams(const long lMethodNum) = 0;
/// Returns default value of method parameter
/**
* @param lMethodNum - method index(starting with 0)
* @param lParamNum - parameter index (starting with 0)
* @param pvarParamDefValue - the pointer to a variable for default value
* @return the result of
*/
virtual bool ADDIN_API GetParamDefValue(const long lMethodNum,
const long lParamNum,
tVariant *pvarParamDefValue) = 0;
/// Does the method have a return value?
/**
* @param lMethodNum - method index (starting with 0)
* @return true if the method has a return value
*/
virtual bool ADDIN_API HasRetVal(const long lMethodNum) = 0;
/// Calls the method as a procedure
/**
* @param lMethodNum - method index (starting with 0)
* @param paParams - the pointer to array of method parameters
* @param lSizeArray - the size of array
* @return the result of
*/
virtual bool ADDIN_API CallAsProc(const long lMethodNum,
tVariant* paParams,
const long lSizeArray) = 0;
/// Calls the method as a function
/**
* @param lMethodNum - method index (starting with 0)
* @param pvarRetValue - the pointer to returned value
* @param paParams - the pointer to array of method parameters
* @param lSizeArray - the size of array
* @return the result of
*/
virtual bool ADDIN_API CallAsFunc(const long lMethodNum,
tVariant* pvarRetValue,
tVariant* paParams,
const long lSizeArray) = 0;
};
///////////////////////////////////////////////////////////////////////////
/**
* This interface is used to change component locale
*/
/// Base interface for component localization.
class LocaleBase
{
public:
virtual ~LocaleBase(){}
/// Changes component locale
/**
* @param loc - new locale (for Windows - rus_RUS,
* for Linux - ru_RU, etc...)
*/
virtual void ADDIN_API SetLocale(const WCHAR_T* loc) = 0;
};
///////////////////////////////////////////////////////////////////////////
/**
* The given interface is generalized, for its obligatory inheritance
* in implementing components.
*/
/// Base interface describing object as a set of properties and methods.
class IComponentBase :
public IInitDoneBase,
public ILanguageExtenderBase,
public LocaleBase
{
public:
virtual ~IComponentBase(){}
};
/// Announcements of exported functions
/**
* These functions should be implemented that component can be loaded and created.
*/
extern "C" long GetClassObject(const WCHAR_T*, IComponentBase** pIntf);
extern "C" long DestroyObject(IComponentBase** pIntf);
extern "C" const WCHAR_T* GetClassNames();
typedef long (*GetClassObjectPtr)(const WCHAR_T* wsName, IComponentBase** pIntf);
typedef long (*DestroyObjectPtr)(IComponentBase** pIntf);
typedef const WCHAR_T* (*GetClassNamesPtr)();
#endif //__COMPONENT_BASE_H__
В основном файле добавляем строку:
#include "ComponentBase.h"
Добавляем новый класс в файл Component.h:
// class Component
class Component : public IComponentBase
{
public:
enum Props
{
ePropLast = 0 // Always last
};
enum Methods
{
eVersion = 0, // Версия Компоненты
eMethLast // Always last
};
Component(void);
virtual ~Component();
};
Добавим файл types.h с содержимым:
#ifndef __CON_TYPES_H__
#define __CON_TYPES_H__
#ifndef __linux__
#include <windows.h>
#endif
#if __GNUC__ >=3
#pragma GCC system_header
#endif
#include "com.h"
#include <time.h>
#include <string.h>
#include <assert.h>
#include <stddef.h>
#define EXTERN_C extern "C"
#ifdef __GNUC__
#define _ANONYMOUS_UNION __extension__
#define _ANONYMOUS_STRUCT __extension__
#else
#define _ANONYMOUS_UNION
#define _ANONYMOUS_STRUCT
#endif //__GNUC__
#ifdef NONAMELESSUNION
#define __VARIANT_NAME_1 u
#define __VARIANT_NAME_2 iface
#define __VARIANT_NAME_3 str
#define __VARIANT_NAME_4 wstr
#else
#define __VARIANT_NAME_1
#define __VARIANT_NAME_2
#define __VARIANT_NAME_3
#define __VARIANT_NAME_4
#endif //NONAMELESSUNION
#define RESULT_FROM_ERRNO(x) ((long)(x) <= 0 ? ((long)(x)) \
: ((long) (((x) & 0x0000FFFF) | (BASE_ERRNO << 16) | 0x80000000)))
#define ADDIN_E_NONE 1000
#define ADDIN_E_ORDINARY 1001
#define ADDIN_E_ATTENTION 1002
#define ADDIN_E_IMPORTANT 1003
#define ADDIN_E_VERY_IMPORTANT 1004
#define ADDIN_E_INFO 1005
#define ADDIN_E_FAIL 1006
#define ADDIN_E_MSGBOX_ATTENTION 1007
#define ADDIN_E_MSGBOX_INFO 1008
#define ADDIN_E_MSGBOX_FAIL 1009
#ifndef ADDIN_API
#ifndef __linux__
#define ADDIN_API __stdcall
#else
//#define ADDIN_API __attribute__ ((__stdcall__))
#define ADDIN_API
#endif //__linux__
#endif //ADDIN_API
#if !defined __linux__
////////////////////////////////////////////////////////////////////////////
// sized integer types
// typedef __int8 int8_t ; ///< 8-bit integer
typedef unsigned __int8 uint8_t ; ///< 8-bit unsigned integer
typedef __int16 int16_t ; ///< 16-bit integer
typedef unsigned __int16 uint16_t ; ///< 16-bit unsigned integer
typedef __int32 int32_t ; ///< 32-bit integer
typedef unsigned __int32 uint32_t ; ///< 32-bit unsigned integer
typedef __int64 int64_t ; ///< 64-bit integer
typedef unsigned __int64 uint64_t ; ///< 64-bit unsigned integer
#else
#include <stdint.h>
#endif
#ifndef __linux__
#define WCHAR_T wchar_t
#else
#define WCHAR_T uint16_t
#endif //__linux__
typedef unsigned short TYPEVAR;
enum ENUMVAR
{
VTYPE_EMPTY = 0,
VTYPE_NULL,
VTYPE_I2, //int16_t
VTYPE_I4, //int32_t
VTYPE_R4, //float
VTYPE_R8, //double
VTYPE_DATE, //DATE (double)
VTYPE_TM, //struct tm
VTYPE_PSTR, //struct str string
VTYPE_INTERFACE, //struct iface
VTYPE_ERROR, //int32_t errCode
VTYPE_BOOL, //bool
VTYPE_VARIANT, //struct _tVariant *
VTYPE_I1, //int8_t
VTYPE_UI1, //uint8_t
VTYPE_UI2, //uint16_t
VTYPE_UI4, //uint32_t
VTYPE_I8, //int64_t
VTYPE_UI8, //uint64_t
VTYPE_INT, //int Depends on architecture
VTYPE_UINT, //unsigned int Depends on architecture
VTYPE_HRESULT, //long hRes
VTYPE_PWSTR, //struct wstr
VTYPE_BLOB, //means in struct str binary data contain
VTYPE_CLSID, //UUID
VTYPE_STR_BLOB = 0xfff,
VTYPE_VECTOR = 0x1000,
VTYPE_ARRAY = 0x2000,
VTYPE_BYREF = 0x4000, //Only with struct _tVariant *
VTYPE_RESERVED = 0x8000,
VTYPE_ILLEGAL = 0xffff,
VTYPE_ILLEGALMASKED = 0xfff,
VTYPE_TYPEMASK = 0xfff
} ;
#if defined (__GNUC__) && !defined (NONAMELESSUNION)
__extension__ /* no named members */
#endif
struct _tVariant
{
_ANONYMOUS_UNION union
{
//int8_t i8Val;
int16_t shortVal;
int32_t lVal;
int intVal;
unsigned int uintVal;
int64_t llVal;
uint8_t ui8Val;
uint16_t ushortVal;
uint32_t ulVal;
uint64_t ullVal;
int32_t errCode;
long hRes;
float fltVal;
double dblVal;
bool bVal;
char chVal;
wchar_t wchVal;
//DATE date;
IID IDVal;
struct _tVariant *pvarVal;
struct tm tmVal;
_ANONYMOUS_STRUCT struct
{
void* pInterfaceVal;
IID InterfaceID;
} __VARIANT_NAME_2/*iface*/;
_ANONYMOUS_STRUCT struct
{
char* pstrVal;
uint32_t strLen; //count of bytes
} __VARIANT_NAME_3/*str*/;
_ANONYMOUS_STRUCT struct
{
WCHAR_T* pwstrVal;
uint32_t wstrLen; //count of symbol
} __VARIANT_NAME_4/*wstr*/;
} __VARIANT_NAME_1;
uint32_t cbElements; //Dimension for an one-dimensional array in pvarVal
TYPEVAR vt;
};
typedef struct _tVariant tVariant;
typedef tVariant tVariantArg;
#if defined(NONAMELESSUNION)
#define TV_JOIN(X, Y) ((X)->u.Y)
#else
#define TV_JOIN(X, Y) ((X)->Y)
#endif
#define TV_VT(X) ((X)->vt)
#define TV_ISBYREF(X) (TV_VT(X)&VT_BYREF)
#define TV_ISARRAY(X) (TV_VT(X)&VT_ARRAY)
#define TV_ISVECTOR(X) (TV_VT(X)&VT_VECTOR)
#define TV_NONE(X) TV_I2(X)
#define TV_UI1(X) TV_JOIN(X, ui8Val)
#define TV_I2(X) TV_JOIN(X, shortVal)
#define TV_I4(X) TV_JOIN(X, lVal)
#define TV_I8(X) TV_JOIN(X, llVal)
#define TV_R4(X) TV_JOIN(X, fltVal)
#define TV_R8(X) TV_JOIN(X, dblVal)
#define TV_I1(X) TV_JOIN(X, i8Val)
#define TV_UI2(X) TV_JOIN(X, ushortVal)
#define TV_UI4(X) TV_JOIN(X, ulVal)
#define TV_UI8(X) TV_JOIN(X, ullVal)
#define TV_INT(X) TV_JOIN(X, intVal)
#define TV_UINT(X) TV_JOIN(X, uintVal)
#ifdef _WIN64
#define TV_INT_PTR(X) TV_JOIN(X, llVal)
#define TV_UINT_PTR(X) TV_JOIN(X, ullVal)
#else
#define TV_INT_PTR(X) TV_JOIN(X, lVal)
#define TV_UINT_PTR(X) TV_JOIN(X, ulVal)
#endif
#define TV_DATE(X) TV_JOIN(X, date)
#define TV_STR(X) TV_JOIN(X, pstrVal)
#define TV_WSTR(X) TV_JOIN(X, pwstrVal)
#define TV_BOOL(X) TV_JOIN(X, bVal)
#define TV_UNKNOWN(X) TV_JOIN(X, pInterfaceVal)
#define TV_VARIANTREF(X) TV_JOIN(X, pvarVal)
void tVarInit(tVariant* tvar);
inline
void tVarInit(tVariant* tvar)
{
assert(tvar != NULL);
memset(tvar, 0, sizeof(tVariant));
TV_VT(tvar) = VTYPE_EMPTY;
}
//----------------------------------------------------------------------------//
// static setter functions...
#define DATA_SET_BEGIN(data_) \
tVarInit(data_);
#define DATA_SET_END(data_, type_) \
TV_VT(data_) = type_;
#define DATA_SET(data_, type_, member_, value_) \
DATA_SET_BEGIN(data_) \
TV_JOIN(data_, member_) = value_; \
DATA_SET_END(data_, type_)
#define DATA_SET_WITH_CAST(data_, type_, member_, cast_, value_) \
DATA_SET_BEGIN(data_) \
TV_JOIN(data_, member_) = cast_ value_; \
DATA_SET_END(data_, type_)
#endif //__CON_TYPES_H__
Добавим файл IMemoryManager.h с содержимым:
/*
* Warning!!!
* DO NOT ALTER THIS FILE!
*/
#ifndef __IMEMORY_MANAGER_H__
#define __IMEMORY_MANAGER_H__
///////////////////////////////////////////////////////////////////////////////
/**
* The given class allocates and releases memory for a component
*/
/// Interface representing memory manager.
class IMemoryManager
{
public:
virtual ~IMemoryManager() {}
/// Allocates memory of specified size
/**
* @param pMemory - the double pointer to variable, that will hold newly
* allocated block of memory of NULL if allocation fails.
* @param ulCountByte - memory size
* @return the result of
*/
virtual bool ADDIN_API AllocMemory (void** pMemory, unsigned long ulCountByte) = 0;
/// Releases memory
/**
* @param pMemory - The double pointer to the memory block being released
*/
virtual void ADDIN_API FreeMemory (void** pMemory) = 0;
};
#endif //__IMEMORY_MANAGER_H__
Так как класс CComponent наследуется от IComponentBase, то в нем должны быть определенные процедуры. Добавляем в файл Component.h описание функций в public:
// IInitDoneBase
virtual bool ADDIN_API Init(void*);
virtual bool ADDIN_API setMemManager(void* mem);
virtual long ADDIN_API GetInfo();
virtual void ADDIN_API Done();
// ILanguageExtenderBase
virtual bool ADDIN_API RegisterExtensionAs(WCHAR_T**);
virtual long ADDIN_API GetNProps();
virtual long ADDIN_API FindProp(const WCHAR_T* wsPropName);
virtual const WCHAR_T* ADDIN_API GetPropName(long lPropNum, long lPropAlias);
virtual bool ADDIN_API GetPropVal(const long lPropNum, tVariant* pvarPropVal);
virtual bool ADDIN_API SetPropVal(const long lPropNum, tVariant* varPropVal);
virtual bool ADDIN_API IsPropReadable(const long lPropNum);
virtual bool ADDIN_API IsPropWritable(const long lPropNum);
virtual long ADDIN_API GetNMethods();
virtual long ADDIN_API FindMethod(const WCHAR_T* wsMethodName);
virtual const WCHAR_T* ADDIN_API GetMethodName(const long lMethodNum,
const long lMethodAlias);
virtual long ADDIN_API GetNParams(const long lMethodNum);
virtual bool ADDIN_API GetParamDefValue(const long lMethodNum, const long lParamNum,
tVariant *pvarParamDefValue);
virtual bool ADDIN_API HasRetVal(const long lMethodNum);
virtual bool ADDIN_API CallAsProc(const long lMethodNum,
tVariant* paParams, const long lSizeArray);
virtual bool ADDIN_API CallAsFunc(const long lMethodNum,
tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray);
// LocaleBase
virtual void ADDIN_API SetLocale(const WCHAR_T* loc);
Итоговый текст модуля Component.cpp после добавления реализаций функций:
// Component.cpp : Определяет экспортируемые функции для DLL.
//
#include "pch.h"
#include "framework.h"
#include "Component.h"
#include "ComponentBase.h"
#include <stdio.h>
#include <string.h>
#include <locale.h>
#define TIME_LEN 34
#define BASE_ERRNO 7
typedef unsigned int uint32_t;
uint32_t convToShortWchar(WCHAR_T** Dest, const wchar_t* Source, uint32_t len = 0);
uint32_t convFromShortWchar(wchar_t** Dest, const WCHAR_T* Source, uint32_t len = 0);
uint32_t getLenShortWcharStr(const WCHAR_T* Source);
// Пример экспортированной переменной
COMPONENT_API int nComponent=0;
// Пример экспортированной функции.
COMPONENT_API int fnComponent(void)
{
return 0;
}
static wchar_t *g_PropNames[] = { L"" };
static wchar_t *g_PropNamesRu[] = { L"" };
static wchar_t *g_MethodNamesRu[] = {
L"Версия",
L"ПолучитьФрагментИзображения"
};
static wchar_t* g_MethodNames[] = {
L"Version",
L"GetImageFragment"
};
static const wchar_t g_kClassNames[] = L"C1CGetImageFragment";
//---------------------------------------------------------------------------//
const wchar_t* kComponentVersion = L"1.0";
const wchar_t* kErrMsg_NoImagePath = L"No image path";
const wchar_t* kErrMsg_NoMFCPath = L"No path to application";
const wchar_t* kErrMsg_NoResultPath = L"No result path";
const wchar_t* kErrMsg_LoadImage = L"Error loading image";
const wchar_t* kErrMsg_Timeout = L"Error timeout expired";
const wchar_t* kErrMsg_InternalError = L"Internal error"; // любые внутренние ошибка кода компоненты
const wchar_t* kErrMsg_NoPicturePaths = L"No picture paths";
//---------------------------------------------------------------------------//
const WCHAR_T* GetClassNames()
{
static WCHAR_T* names = 0;
if (!names)
::convToShortWchar(&names, g_kClassNames);
return names;
}
uint32_t convToShortWchar(WCHAR_T** Dest, const wchar_t* Source, uint32_t len)
{
if (!len)
len = ::wcslen(Source) + 1;
if (!*Dest)
*Dest = new WCHAR_T[len];
WCHAR_T* tmpShort = *Dest;
wchar_t* tmpWChar = (wchar_t*)Source;
uint32_t res = 0;
::memset(*Dest, 0, len * sizeof(WCHAR_T));
do
{
*tmpShort++ = (WCHAR_T)*tmpWChar++;
++res;
} while (len-- && *tmpWChar);
return res;
}
//---------------------------------------------------------------------------//
uint32_t convFromShortWchar(wchar_t** Dest, const WCHAR_T* Source, uint32_t len)
{
if (!len)
len = getLenShortWcharStr(Source) + 1;
if (!*Dest)
*Dest = new wchar_t[len];
wchar_t* tmpWChar = *Dest;
WCHAR_T* tmpShort = (WCHAR_T*)Source;
uint32_t res = 0;
::memset(*Dest, 0, len * sizeof(wchar_t));
do
{
*tmpWChar++ = (wchar_t)*tmpShort++;
++res;
} while (len-- && *tmpShort);
return res;
}
//---------------------------------------------------------------------------//
uint32_t getLenShortWcharStr(const WCHAR_T* Source)
{
uint32_t res = 0;
WCHAR_T* tmpShort = (WCHAR_T*)Source;
while (*tmpShort++)
++res;
return res;
}
//---------------------------------------------------------------------------//
long GetClassObject(const WCHAR_T* wsName, IComponentBase** pInterface)
{
if (!*pInterface)
{
*pInterface = new CComponent;
return (long)*pInterface;
}
return 0;
}
// CComponent
//---------------------------------------------------------------------------//
CComponent::CComponent()
{
m_iMemory = 0;
m_iConnect = 0;
}
//---------------------------------------------------------------------------//
CComponent::~CComponent()
{
}
bool CComponent::Init(void* pConnection)
{
m_iConnect = (IAddInDefBase*)pConnection;
return m_iConnect != NULL;
}
//---------------------------------------------------------------------------//
long CComponent::GetInfo()
{
// Component should put supported component technology version
// This component supports 2.0 version
return 2000;
}
//---------------------------------------------------------------------------//
void CComponent::Done()
{
}
/////////////////////////////////////////////////////////////////////////////
// ILanguageExtenderBase
//---------------------------------------------------------------------------//
bool CComponent::RegisterExtensionAs(WCHAR_T** wsExtensionName)
{
const wchar_t* wsExtension = L"AddInNativeExtension";
int iActualSize = ::wcslen(wsExtension) + 1;
WCHAR_T* dest = 0;
if (m_iMemory)
{
if (m_iMemory->AllocMemory((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T)))
::convToShortWchar(wsExtensionName, wsExtension, iActualSize);
return true;
}
return false;
}
//---------------------------------------------------------------------------//
long CComponent::GetNProps()
{
// You may delete next lines and add your own implementation code here
return ePropLast;
}
//---------------------------------------------------------------------------//
long CComponent::FindProp(const WCHAR_T* wsPropName)
{
long plPropNum = -1;
wchar_t* propName = 0;
::convFromShortWchar(&propName, wsPropName);
plPropNum = findName(g_PropNames, propName, ePropLast);
if (plPropNum == -1)
plPropNum = findName(g_PropNamesRu, propName, ePropLast);
delete[] propName;
return plPropNum;
}
//---------------------------------------------------------------------------//
const WCHAR_T* CComponent::GetPropName(long lPropNum, long lPropAlias)
{
if (lPropNum >= ePropLast)
return NULL;
wchar_t* wsCurrentName = NULL;
WCHAR_T* wsPropName = NULL;
int iActualSize = 0;
switch (lPropAlias)
{
case 0: // First language
wsCurrentName = g_PropNames[lPropNum];
break;
case 1: // Second language
wsCurrentName = g_PropNamesRu[lPropNum];
break;
default:
return 0;
}
iActualSize = wcslen(wsCurrentName) + 1;
if (m_iMemory && wsCurrentName)
{
if (m_iMemory->AllocMemory((void**)&wsPropName, iActualSize * sizeof(WCHAR_T)))
::convToShortWchar(&wsPropName, wsCurrentName, iActualSize);
}
return wsPropName;
}
//---------------------------------------------------------------------------//
bool CComponent::GetPropVal(const long /*lPropNum*/, tVariant* /*pvarPropVal*/)
{
return false;
}
//---------------------------------------------------------------------------//
bool CComponent::SetPropVal(const long /*lPropNum*/, tVariant* /*varPropVal*/)
{
return false;
}
//---------------------------------------------------------------------------//
bool CComponent::IsPropReadable(const long /*lPropNum*/)
{
return false;
}
//---------------------------------------------------------------------------//
bool CComponent::IsPropWritable(const long /*lPropNum*/)
{
return false;
}
//---------------------------------------------------------------------------//
long CComponent::GetNMethods()
{
return eMethLast;
}
//---------------------------------------------------------------------------//
long CComponent::FindMethod(const WCHAR_T* wsMethodName)
{
long plMethodNum = -1;
wchar_t* name = 0;
::convFromShortWchar(&name, wsMethodName);
plMethodNum = findName(g_MethodNames, name, eMethLast);
if (plMethodNum == -1)
plMethodNum = findName(g_MethodNamesRu, name, eMethLast);
return plMethodNum;
}
//---------------------------------------------------------------------------//
const WCHAR_T* CComponent::GetMethodName(const long lMethodNum, const long lMethodAlias)
{
if (lMethodNum >= eMethLast)
return NULL;
wchar_t* wsCurrentName = NULL;
WCHAR_T* wsMethodName = NULL;
int iActualSize = 0;
switch (lMethodAlias)
{
case 0: // First language
wsCurrentName = g_MethodNames[lMethodNum];
break;
case 1: // Second language
wsCurrentName = g_MethodNamesRu[lMethodNum];
break;
default:
return 0;
}
iActualSize = wcslen(wsCurrentName) + 1;
if (m_iMemory && wsCurrentName)
{
if (m_iMemory->AllocMemory((void**)&wsMethodName, iActualSize * sizeof(WCHAR_T)))
::convToShortWchar(&wsMethodName, wsCurrentName, iActualSize);
}
return wsMethodName;
}
//---------------------------------------------------------------------------//
long CComponent::GetNParams(const long lMethodNum)
{
switch (lMethodNum)
{
case eVersion:
return 0;
default:
return 0;
}
return 0;
}
//---------------------------------------------------------------------------//
bool CComponent::GetParamDefValue(const long lMethodNum, const long lParamNum,
tVariant* pvarParamDefValue)
{
TV_VT(pvarParamDefValue) = VTYPE_EMPTY;
switch (lMethodNum)
{
case eVersion:
default:
return false;
}
return false;
}
//---------------------------------------------------------------------------//
bool CComponent::HasRetVal(const long lMethodNum)
{
switch (lMethodNum)
{
case eVersion:
return true;
default:
return false;
}
return false;
}
//---------------------------------------------------------------------------//
bool CComponent::CallAsProc(const long lMethodNum,
tVariant* paParams, const long lSizeArray)
{
switch (lMethodNum)
{
case eVersion:
default:
return false;
}
return false; // as func
}
//---------------------------------------------------------------------------//
bool CComponent::CallAsFunc(const long lMethodNum,
tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray)
{
switch (lMethodNum)
{
case eVersion:
{
if (pvarRetValue)
{
size_t strLen = wcslen(kComponentVersion);
if (m_iMemory->AllocMemory((void**)&pvarRetValue->pwstrVal, (strLen + 1) * sizeof(kComponentVersion[0])))
{
wcscpy_s(pvarRetValue->pwstrVal, strLen + 1, kComponentVersion);
pvarRetValue->wstrLen = strLen;
TV_VT(pvarRetValue) = VTYPE_PWSTR;
}
}
break;
}
default:
return false;
}
return true;
}
//---------------------------------------------------------------------------//
void CComponent::SetLocale(const WCHAR_T* loc)
{
#ifndef __linux__
_wsetlocale(LC_ALL, loc);
#else
//We convert in char* char_locale
//also we establish locale
//setlocale(LC_ALL, char_locale);
#endif
}
/////////////////////////////////////////////////////////////////////////////
// LocaleBase
//---------------------------------------------------------------------------//
bool CComponent::setMemManager(void* mem)
{
m_iMemory = (IMemoryManager*)mem;
return m_iMemory != 0;
}
//---------------------------------------------------------------------------//
void CComponent::addError(uint32_t wcode, const wchar_t* source,
const wchar_t* descriptor, long code)
{
if (m_iConnect)
{
WCHAR_T* err = 0;
WCHAR_T* descr = 0;
::convToShortWchar(&err, source);
::convToShortWchar(&descr, descriptor);
m_iConnect->AddError(wcode, err, descr, code);
delete[] err;
delete[] descr;
}
}
//---------------------------------------------------------------------------//
void CComponent::addError(const wchar_t* errorText)
{
if (m_iConnect)
m_iConnect->AddError(ADDIN_E_NONE, L"C1CGetImageFragment", errorText, 0);
}
//---------------------------------------------------------------------------//
long CComponent::findName(wchar_t* names[], const wchar_t* name,
const uint32_t size) const
{
long ret = -1;
for (uint32_t i = 0; i < size; i++)
{
if (!wcscmp(names[i], name))
{
ret = i;
break;
}
}
return ret;
}
Итоговый текст модуля Component.h:
// Приведенный ниже блок ifdef — это стандартный метод создания макросов, упрощающий процедуру
// экспорта из библиотек DLL. Все файлы данной DLL скомпилированы с использованием символа COMPONENT_EXPORTS
// Символ, определенный в командной строке. Этот символ не должен быть определен в каком-либо проекте,
// использующем данную DLL. Благодаря этому любой другой проект, исходные файлы которого включают данный файл, видит
// функции COMPONENT_API как импортированные из DLL, тогда как данная DLL видит символы,
// определяемые данным макросом, как экспортированные.
#ifdef COMPONENT_EXPORTS
#define COMPONENT_API __declspec(dllexport)
#else
#define COMPONENT_API __declspec(dllimport)
#endif
#include "ComponentBase.h"
#include "AddInDefBase.h"
#include "IMemoryManager.h"
extern COMPONENT_API int nComponent;
COMPONENT_API int fnComponent(void);
// class Component
class CComponent : public IComponentBase
{
public:
enum Props
{
ePropLast = 0 // Always last
};
enum Methods
{
eVersion = 0, // Версия Компоненты
eMethLast // Always last
};
CComponent(void);
virtual ~CComponent();
// IInitDoneBase
virtual bool ADDIN_API Init(void*);
virtual bool ADDIN_API setMemManager(void* mem);
virtual long ADDIN_API GetInfo();
virtual void ADDIN_API Done();
// ILanguageExtenderBase
virtual bool ADDIN_API RegisterExtensionAs(WCHAR_T**);
virtual long ADDIN_API GetNProps();
virtual long ADDIN_API FindProp(const WCHAR_T* wsPropName);
virtual const WCHAR_T* ADDIN_API GetPropName(long lPropNum, long lPropAlias);
virtual bool ADDIN_API GetPropVal(const long lPropNum, tVariant* pvarPropVal);
virtual bool ADDIN_API SetPropVal(const long lPropNum, tVariant* varPropVal);
virtual bool ADDIN_API IsPropReadable(const long lPropNum);
virtual bool ADDIN_API IsPropWritable(const long lPropNum);
virtual long ADDIN_API GetNMethods();
virtual long ADDIN_API FindMethod(const WCHAR_T* wsMethodName);
virtual const WCHAR_T* ADDIN_API GetMethodName(const long lMethodNum,
const long lMethodAlias);
virtual long ADDIN_API GetNParams(const long lMethodNum);
virtual bool ADDIN_API GetParamDefValue(const long lMethodNum, const long lParamNum,
tVariant* pvarParamDefValue);
virtual bool ADDIN_API HasRetVal(const long lMethodNum);
virtual bool ADDIN_API CallAsProc(const long lMethodNum,
tVariant* paParams, const long lSizeArray);
virtual bool ADDIN_API CallAsFunc(const long lMethodNum,
tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray);
// LocaleBase
virtual void ADDIN_API SetLocale(const WCHAR_T* loc);
private:
long findName(wchar_t* names[], const wchar_t* name, const uint32_t size) const;
void addError(uint32_t wcode, const wchar_t* source,
const wchar_t* descriptor, long code);
// добавление ошибки в Предприятие в момент вызова функции компоненты
void addError(const wchar_t* errorText);
// Attributes
IAddInDefBase* m_iConnect;
IMemoryManager* m_iMemory;
bool m_boolEnabled;
uint32_t m_uiTimer;
};
После всего этого пробуем собрать проект. Возможно будет ошибка преобразования wchar_t, для решения можно поменять настройки проекта: