First of all I am using Mingw 4.8 as the compiler of the C++ DLL in Code:blocks 13.12 and Lazarus 1.4.2 for working with the pascal code.(windows 7)
I need to generete a dll in c++ or c that can be called from a pascal program.
The problem is that my knowlegde about pascal is null, It dosn't look really complicate to make a simple program but I can't find good information about how to import and use a C/C++ DLL.
The only thing that moreless worked was this: http://www.drbob42.com/delphi/headconv.htm
My real code:
Pascal:
funtion hello():Integer; external 'function' index 1;
...
Label1.Caption:=IntToStr(hello());
C++ DLL header:
#ifndef function_H
#define function_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef BUILDING_DLL
#define FUNCTION_DLL __declspec(dllexport)
#else
#define FUNCTION_DLL __declspec(dllimport)
#endif
int __stdcall FUNCTION_DLL hello( );
#ifdef __cplusplus
}
#endif
#endif
C++ file:
#include <stdio.h>
#include "function.h"
__stdcall int hello( )
{
return 8;
}
But when try to pass any argument or do something complicated with the function,starts to give randoms numbers.
This is the new code:
Pascal:
function function1(t1:Integer):Integer; external 'function' index 1;
...
entero:=8;
Label1.Caption:=IntToStr(function1(entero2));
Also I update the c++ code to this:
C++:
#include <stdio.h>
#include "function.h"
__stdcall int function1(int t1)
{
return t1*2;
}
Header:
#ifndef funtion_H
#define funtion_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef BUILDING_DLL
#define FUNCTION_DLL __declspec(dllexport)
#else
#define FUNCTION_DLL __declspec(dllimport)
#endif
int __stdcall FUNCTION_DLL function1(int t1);
#ifdef __cplusplus
}
#endif
#endif
I aslo read this other info:http://www.jrsoftware.org/ishelp/index.php?topic=scriptdll. And tried to implement the dll call like this:
Pascal:
function function1(t1: Integer): Integer; external 'function1#files:function.dll';
But I receive an error saying that:
The procedure entry point function1 could not be located in the
dynamic link library function.dll
I'm looking for an example that works or a online tutorial or something to continue working because I am very stuck with this.
Thank you in advance.
You need to make the calling conventions match. Your C++ code uses __stdcall. The Pascal code does not specify a calling convention and so defaults to register.
Declare the Pascal import like this:
function function1(t1:Integer):Integer; stdcall; external 'function' index 1;
Are you quite sure that you need to use an index when importing? It is much more common to import by name than by ordinal. I'd expect to see the import looking like this:
function function1(t1:Integer):Integer; stdcall; external 'function';
The reason why the function with no parameters succeeds is that for a parameterless function, the differences between calling convention do not matter. Once you start passing an argument, stdcall means that the argument is passed via the stack, and register means it is passed in a register. This mismatch explains the behaviour you observe.
Related
Basically I have a dll project in visual studio. I'm linking this dll project to a second project successfully but as soon as I try to use extern variables things go wrong. I've seperated my extern variables into a single header and source file from everything else so I can isolate the problem and potential solutions. I've scowered the internet for hours now and I feel like I've tried everything. I am beginning to think it might be a compile flag? Anyway, heres my code.
macros.h
#pragma once
// dll management
#ifdef TOAST_EXPORT
#ifdef _MSC_VER
#define TAPI __declspec(dllexport)
#else
#define TAPI __attribute__((visibility("default")))
#endif
#else
#ifdef _MSC_VER
#define TAPI __declspec(dllimport)
#else
#define TAPI
#endif
#endif
globals.h
#pragma once
#define TOAST_EXPORT
#include "macros.h"
namespace toast
{
TAPI extern const char c;
}
globals.c
Note that I tried this without const and made no assignment here
#pragma once
#include "globals.h"
namespace toast
{
const char c = 'a';
}
main.c (from the project that compiles to an exe)
#include <globals.h>
int main()
{
char c = toast::c;
return 0;
}
So far I've tried making a lot of subtle changes like reordering extern and const and such. I've also done it both with just extern and just const. Still produces the same unresolved external symbol "char const toast::c" error. Keep in mind that I can create instances of classes and call their methods from the dll successfully and thats with things like class TAPI logger... and such.
Hello I am currently trying to export an array from a Dll into a C-based data-analysis program called Uniplot.
I am able to call the DLL and get it running, though I cant access the data provided by the Dll. I am not really well-served on this subject but I am guessing it has something to do with releasing the function to get rid of the pointers, or the data type in general even.
Header.h
// considering export into C application
#ifdef __cplusplus
extern "C"
{
#endif
// prepare functions for later export/import from DLL
#ifdef CALC_EXPORTS
#define CALCDLL_API __declspec(dllexport)
#else
#define CALCDLL_API __declspec(dllimport)
#endif
typedef double t_mda[150];
typedef double t_sda[50];
typedef double t_oda[150];
/*===========================
functions
============================*/
// general function
CALCDLL_API double* CALC (t_mda MDA, t_sda SDA);
....
#ifdef __cplusplus
}
#endif
.cpp
t_oda ODA;
CALCDLL_API double* CALC (t_mda MDA, t_sda SDA) {
...
//data output
return ODA;
}
CALC is generating the data and saving it to the ODA-array which I would like to use in another application. What are the changes I need to make to get that running?
I have a set of functions written in C that I need to be able to call from another project written in C++. The C code is essentially some functions that do some calculations on a large data set. I didn't write them - all I want to do is allow my C++ project to be able to call those functions. My solution was to create a DLL for the C code and link it to my C++ project.
In order to make the DLL, I structured myCproj.h (the header in the C project, not C++ project) like so:
#ifdef __cplusplus
extern "C" {
#endif
struct __declspec(dllexport) neededStruct {
int a;
//I need to be able to initialize this struct in my C++ project.
}
__declspec(dllexport) void neededFunc( struct neededStruct *input ) {}
//I need to be able to call this function from my C++ project and feed
//it my local instance of neededStruct.
#ifdef __cplusplus
}
#endif
The src file, myCproj.c, was not changed at all. The function definitions do not have __declspec(dllexport)in front of them, nor is extern "C" inserted anywhere. The code compiles without error and produces myCproj.dll and myCproj.lib.
I then tell my C++ project in VS where to find myCproj.lib and myCproj.h accordingly and copy the DLL over to the directory where my C++ executable lives. To use the DLL, I gave myCPPproj.cpp the following addition:
#define DLLImport __declspec(dllimport)
struct DLLImport neededStruct input;
input.a = 0;
extern "C" DLLImport void neededFunc( &input );
However, I get error EO335 'linkage specification is not allowed' on that last line. What am I doing wrong?
It is preferable to use the same header for both the library and using code.
As mentioned, it is usually done by a conditional define, like the following:
MyLibrary.h:
#if defined(MYLIBRARY_API)
#define MYLIBRARY_EXPORTS __declspec(dllexport)
#else
#define MYLIBRARY_EXPORTS __declspec(dllimport)
#endif
#if defined(__cplusplus)
extern "C" {
#endif
MYLIBRARY_API bool MyLibFunc();
#if defined(__cplusplus)
#endif
MyLibrary.c:
#include "MyLibrary.h"
void MyLibFunc()
{
....
}
App.cpp:
#include <MyLibrary.h>
int main()
{
MyLibFunc();
}
The symbol MYLIBRARY_API will be defined for the library project (usually as a /D on the compiler command line). And if you use visual studio that is pretty much exactly what you get when creating a dll project with exports.
For learning purposes, I'm trying to load a DLL into MATLAB which calls functions defined in another DLL. I'm new to all of this, and haven't yet been able to figure out how I would go about doing this, and nor have I managed to find any relevant resources.
I wrote a small DLL in C++ which goes something like this:
//example_dll.h
#ifndef EXAMPLE_DLL_H
#define EXAMPLE_DLL_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef BUILDING_EXAMPLE_DLL
#define EXAMPLE_DLL __declspec(dllexport)
#else
#define EXAMPLE_DLL __declspec(dllimport)
#endif
int EXAMPLE_DLL Double(int x);
#ifdef __cplusplus
}
#endif
#endif // EXAMPLE_DLL_H
and the source file:
//example_dll.cpp
#include <stdio.h>
#include "example_dll.h"
int Double(int x)
{
return 2 * x;
}
This I built using MinGW w64 and loaded into matlab using loadlibrary('example_dll') without any problems.
I now want to define the function
int Double(int x)
{
return 2 * x;
}
In another DLL, (let's call it DLL2) and to call that function from my example_dll.
What would be the easiest way to do it?
I would appreciate a short example code (preferably for run-time dynamic linking, and without the use of module definition (.def) files) or a link to a relevant resource on the interwebs.
Thanks!
SOLUTION TO SIMPLE EXAMPLE:
I think I got the solution. It seems to be working anyway.
I created a DLL named interface_DLL which I loaded into MATLAB and from which I called my function in example_dll
here it is:
//interface_dll.h
#ifndef INTERFACE_DLL_H
#define INTERFACE_DLL_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef BUILDING_INTERFACE_DLL
#define INTERFACE_DLL __declspec(dllexport)
#else
#define INTERFACE_DLL __declspec(dllimport)
#endif
int INTERFACE_DLL Quadruple(int x);
#ifdef __cplusplus
}
#endif
#endif // INTERFACE_DLL_H
and the source file:
//interface_dll.cpp
#include <windows.h>
#include <stdio.h>
#include "interface_dll.h"
#include "example_dll.h"
int Quadruple(int x)
{
/* get handle to dll */
HINSTANCE hGetProcIDDLL = LoadLibrary("C:\\Users\\uidr0605\\Documents\\ExampleDLL\\example_dll.dll");
/* get pointer to the function in the dll*/
FARPROC lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLL),"Double");
/*
Define the Function in the DLL for reuse. This is just prototyping the dll's function.
A mock of it. Use "stdcall" for maximum compatibility.
*/
typedef int (__stdcall * pICFUNC)(int);
pICFUNC Double;
Double = pICFUNC(lpfnGetProcessID);
/* The actual call to the function contained in the dll */
int intMyReturnVal = Double(x);
intMyReturnVal = Double(intMyReturnVal);
/* Release the Dll */
FreeLibrary(hGetProcIDDLL);
/* The return val from the dll */
return intMyReturnVal;
}
I load it from MATLAB as follows:
%loadDLL.m
path = 'C:\Path\to\DLL\';
addpath(path);
loadlibrary('interface_dll')
i = 2;
x = calllib('interface_dll', 'Quadruple', i)
The reason I'm going through this process is that the MATLAB shared library interface supports C library routines only and not C++ classes.
My idea of a workaround is to use an intermediate DLL to act as an interface between MATLAB and the DLL who's classes I intend to access.
Is there a better way of doing this?
FURTHER QUESTIONS:
Can anyone please explain the significance of the line typedef int (__stdcall * pICFUNC)(int); as applied here?
What would I have to add or what changes would I have to make if I wanted to call a function in a class in example_dll?
EDIT: I added the following code to the example_dll header file:
class EXAMPLE_DLL MyClass
{
public:
int add2(int);
};
#ifdef __cplusplus
extern "C" {
#endif
MyClass EXAMPLE_DLL *createInstance(){
return new MyClass();
}
void EXAMPLE_DLL destroyInstance(MyClass *ptrMyClass){
delete ptrMyClass;
}
#ifdef __cplusplus
}
#endif
Further question 1
The following definition
typedef int (__stdcall * pICFUNC)(int);
defines a new type pICFUNC which is a pointer to a function which takes an int and returns an int. Also, the function must be called according to the __stdcall calling convention, which specifies how arguments must be passed and how to retrieve the return value.
This link explains typedef with function pointers. Have a look also at the following section, Using typedef with type casts, since on line
Double = pICFUNC(lpfnGetProcessID);
pICFUNC is used to cast instead.
Further question 2
The following is a very trivial example to give an idea. If you have a class in example_dll called MyClass which has a method
int add(int num);
you could implement the following functions:
MyClass *createInstance(){
return new MyClass();
}
void destroyInstance(MyClass *ptrMyClass){
delete ptrMyClass;
}
These function need to be extern "C" and you could import them with GetProcAddress. Then, it would be just a matter of creating an instance, calling its methods through the pointer and eventually destroying it.
EDIT: Some hints for the implementation
Import the function to create the instance
FARPROC lpfnCreateInstance = GetProcAddress(HMODULE (hGetProcIDDLL), "createInstance");
Declare a proper pointer type for the function (returns a MyClass*, no arguments)
typedef MyClass* (__stdcall * pCREATINST)();
Cast lpfnCreateInstance
pCREATINST createInstance;
createInstance = pCREATINST(lpfnCreateInstance)
Create your instance
MyClass *myInstance = creatInstance();
Then you don't need a wrapper for add, you can just call it from your pointer.
int res = myInstance->add(123);
You should do the same for destroyInstance, being careful with the types
Please note that I can't test this code, but it should be the right approach.
I started studying DLL's with implicit linking. I don't really fully understand how it works. Please correct me where I'm wrong.
I failed to compile the next code(3 modules):
MyLib.h
#ifdef MYLIBAPI
#else
#define MYLIBAPI extern "C" __declspec(dllimport)
#endif
MYLIBAPI int g_nResult;
MYLIBAPI int Add(int nLeft, int nRight);
As far as I understand this is the header of the DLL. #define MYLIBAPI extern "C" __declspec(dllimport) means that here we are going to declare some functions/variables that will be described in devoted .cpp file and will be contained in a DLL.
MyLibFile1.cpp
#include <windows.h>
#define MYLIBAPI extern "C" __declspec(dllexport)
#include "MyLib.h"
int g_nResult;
int Add(int nLeft, int nRight) {
g_nResult = nLeft + nRight;
return(g_nResult);
}
So, this is obviously the file where our functions are implemented. This is the part of the DLL, right?
MyExeFile1.cpp
#include <windows.h>
#include <strsafe.h>
#include <stdlib.h>
#include "MyLib.h"
int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int) {
int nLeft = 10, nRight = 25;
TCHAR sz[100];
StringCchPrintf(sz, _countof(sz), TEXT("%d + %d = %d"),
nLeft, nRight, Add(nLeft, nRight));
MessageBox(NULL, sz, TEXT("Calculation"), MB_OK);
StringCchPrintf(sz, _countof(sz),
TEXT("The result from the last Add is: %d"), g_nResult);
MessageBox(NULL, sz, TEXT("Last Result"), MB_OK);
return(0);
}
So, this is the executable file where we use the functions from the library.
The whole thing doesn't work. I tried to put this all into one directory and compile at once. I tried first to compile a DLL from the first two modules(successfully) and then compile the executable (changing the path to the header file). However it resulted in 2 errors both times:
error LNK2019: unresolved external symbol _WinMain#16 referenced in function ___tmainCRTStartup
\Visual Studio 2008\Projects\MyExeFile1\Debug\MyExeFile1.exe : fatal error LNK1120: 1 unresolved externals
What' s the correct way to do that - what should I change in the code and how should I compile the code (I use VS2008)?
Thanks.
#include <tchar.h> to solve the linker error.
Your header file should look like this:
#ifdef BUILDING_DLL
# define MYLIBAPI extern "C" __declspec(dllexport)
#else
# define MYLIBAPI extern "C" __declspec(dllimport)
#endif
MYLIBAPI int __stdcall Add(int nLeft, int nRight);
Right-click your DLL project in Solution Explorer, Properties, C/C++, Preprocessor, Preprocessor Definitions, add "BUILDING_DLL". Repeat for the Release configuration.
You can verify that your DLL properly exports the functions with Dumpbin.exe /exports.
The __declspec(dllimport) declarator is not strictly necessary, it does however make it more efficient. The __stdcall attribute is not necessary either, it does however make your DLL usuable from any language that supports calling DLL exports.
Change _tWinMain to WinMain in MyExeFile1.cpp. It is looking for your entry point to be named WinMain not _tWinMain and so the linker is complaining that it can't find WinMain.
There are project settings that determine what name the entry point function should be, but I'm not sure which one would require _tWinMain.
Edit
According to this posting, _tWinMain is a define that maps to WinMain if you include tchar.h.link text
Does it even compile? Shouldn't you #include <tchar.h> for all TCHAR types and definitions to work?