[C] COM-object gebruiken met Cygwin

Pagina: 1
Acties:

  • ari3
  • Registratie: Augustus 2002
  • Niet online
Ik heb een DLL die ik wil gebruiken vanuit een C-programma. De ontwikkelomgeving is Cygwin.

De DLL is gemaakt in Delphi en is een in-process COM-object. In Delphi 7 kun je een bijbehorend bronbestand genereren waarin de interfaces, methoden en enumeraties staan. Dit wil ik dus ook doen voor Cygwin.

Ik heb het onderstaande al geprobeerd, maar dat werkt volgens mij alleen met DLL's die alle beschikbare functies exporteren. Helaas retourneert GetProcAddress gewoon NULL wat er op wijst dat de functie niet gevonden kan worden ofwel de functies worden niet geëxporteerd.

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <windows.h>
#include <stdio.h>

typedef void (__cdecl *_Logout)();

_Logout enabled_Logout = NULL;

void enable_foo(void) {
        void *dll = LoadLibrary("foo.dll");
        if (dll == NULL) {
                fprintf(stderr, "Failed to load foo.dll");
                exit(1);
        }
        enabled_Logout = (_Logout) GetProcAddress(dll, "Logout");
        printf("%p", GetProcAddress(dll, "Logout"));
}

int main(void) {
        printf("Hello world!\n");
        enable_foo();
        printf("%p", enabled_Logout);
}


Ik google me scheel maar kan niets vinden over het linken met een COM-object. Weten jullie mischien hoe het moet?

"Kill one man, and you are a murderer. Kill millions of men, and you are a conqueror. Kill them all, and you are a god." -- Jean Rostand


  • igmar
  • Registratie: April 2000
  • Laatst online: 29-06 18:56

igmar

ISO20022

Bij de beeste devkits (zo ook die van Borland) zit een tooltje waarmee je DLL exports kan bekijken. Uitermate handig om te bepalen of een bepaalde functie wordt geexporteerd.

Ik zou daarmee eens beginnen. Hetgeen waar je ook op moet letten (daar heb ik met VC last van gehad) is dat je files als C compiled, en niet als c++, want anders zijn je symboolnamen gemangled.. Hernoemen naar .c was bij mij de oplossing.

  • ari3
  • Registratie: Augustus 2002
  • Niet online
igmar schreef op 10 november 2003 @ 14:52:
Bij de beeste devkits (zo ook die van Borland) zit een tooltje waarmee je DLL exports kan bekijken. Uitermate handig om te bepalen of een bepaalde functie wordt geexporteerd.

Ik zou daarmee eens beginnen. Hetgeen waar je ook op moet letten (daar heb ik met VC last van gehad) is dat je files als C compiled, en niet als c++, want anders zijn je symboolnamen gemangled.. Hernoemen naar .c was bij mij de oplossing.
Dat heb ik gedaan en alleen de volgende functies worden geëxporteerd:
- DllUnregisterServer
- DllRegisterServer
- DllCanUnloadNow
- DllGetClassObject

Er missen er dus heel veel.

"Kill one man, and you are a murderer. Kill millions of men, and you are a conqueror. Kill them all, and you are a god." -- Jean Rostand


  • igmar
  • Registratie: April 2000
  • Laatst online: 29-06 18:56

igmar

ISO20022

ari3 schreef op 10 november 2003 @ 15:11:
Dat heb ik gedaan en alleen de volgende functies worden geëxporteerd:
- DllUnregisterServer
- DllRegisterServer
- DllCanUnloadNow
- DllGetClassObject
Dat zijn interfaces voor COM. Je zal of een ander type project moeten aanmaken, of Delphi moeten overhalen om de rest ook te exporteren.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

igmar schreef op 10 november 2003 @ 14:52:
Bij de beeste devkits (zo ook die van Borland) zit een tooltje waarmee je DLL exports kan bekijken. Uitermate handig om te bepalen of een bepaalde functie wordt geexporteerd.

Ik zou daarmee eens beginnen. Hetgeen waar je ook op moet letten (daar heb ik met VC last van gehad) is dat je files als C compiled, en niet als c++, want anders zijn je symboolnamen gemangled.. Hernoemen naar .c was bij mij de oplossing.
En daarom exporteer je dat soort functies altijd als extern "c" :z

Professionele website nodig?


  • ari3
  • Registratie: Augustus 2002
  • Niet online
igmar schreef op 10 november 2003 @ 15:12:
[...]


Dat zijn interfaces voor COM. Je zal of een ander type project moeten aanmaken, of Delphi moeten overhalen om de rest ook te exporteren.
Het probleem is dus dat ik alleen de DLL heb en niet de broncode daarvan. Blijkbaar kun je van een COM-object d.m.v. die interface een lijst krijgen van alle functies en bijbehorende entry-points?

"Kill one man, and you are a murderer. Kill millions of men, and you are a conqueror. Kill them all, and you are a god." -- Jean Rostand


Verwijderd

Haal dmv oleview de idl uit je com object, haal 'm door de midl compiler die spuugt daarna een header file uit die je kan gebruiken in je c/c++ programma, aangezien dit allemaal vrij lastige stof is raad ik je aan eerst een aantal COM tutorials te doorlopen anders ben je gegarandeerd kansloos.

  • ari3
  • Registratie: Augustus 2002
  • Niet online
Verwijderd schreef op 10 november 2003 @ 15:50:
Haal dmv oleview de idl uit je com object, haal 'm door de midl compiler die spuugt daarna een header file uit die je kan gebruiken in je c/c++ programma, aangezien dit allemaal vrij lastige stof is raad ik je aan eerst een aantal COM tutorials te doorlopen anders ben je gegarandeerd kansloos.
Goede tip! Hiermee kwam ik verder... Oleview kon ik downloaden bij Microsoft, de MIDL compiler helaas niet. Ik heb de trial versie van Borland C++ 6 binnengehaald omdat daar de Microsoft Platform SDK wordt meegeleverd. Ik heb dus nu het IDL-bestand uit het COM-object getrokken. Het genereren van de C headers lukt nog niet helemaal. Ik heb het volgende CMD scriptje gemaakt:
code:
1
2
3
4
5
6
7
8
9
10
11
@setlocal
@set IDL=foo.IDL
@set MTL="C:\Program Files\Borland\CBuilder6\Bin\midl.exe"
@set INCLUDE=C:\Program Files\Borland\CBuilder6\Include\Idl;C:\Program Files\Borland\CBuilder6\Include
@set PATH=C:\cygwin\bin;%PATH%

@set CPP=C:\cygwin\bin\cpp.exe
@set CPP_ARGS=-I"C:\cygwin\usr\include\w32api"

%MTL% /nologo /cpp_cmd %CPP% /cpp_opt %CPP_ARGS% /mktyplib203 /win32 %IDL%
@endlocal


Bij executie krijg ik het volgende resultaat:
code:
1
2
3
4
5
6
7
8
9
10
C:\foo>"C:\Program Files\Borland\CBuilder6\Bin\midl.exe" /nologo /cpp_cmd C:\cygwin\bin\cpp.exe /cpp_opt -I"C:\cygwin\usr\include\w32api" /mktyplib203 /win32 foo.IDL
Processing .\foo.IDL
Processing C:\Program Files\Borland\CBuilder6\Include\Idl\oaidl.idl
Processing C:\Program Files\Borland\CBuilder6\Include\Idl\objidl.idl
Processing C:\Program Files\Borland\CBuilder6\Include\Idl\unknwn.idl
Processing C:\Program Files\Borland\CBuilder6\Include\Idl\wtypes.idl
Processing C:\Program Files\Borland\CBuilder6\Include\basetsd.h
Processing C:\Program Files\Borland\CBuilder6\Include\guiddef.h
C:/Program Files/Borland/CBuilder6/Include/Idl/unknwn.idl(155) : error MIDL2025 : syntax error : expecting a type specification near "("
C:/Program Files/Borland/CBuilder6/Include/Idl/unknwn.idl(155) : error MIDL2026 : cannot recover from earlier syntax errors; aborting compilation


Waarom krijg ik hier een syntax error? Het bestand unknwn.idl is niet door mij gemaakt, maar werd meegeleverd met Borland C++ Builder en kan toch niet fout zijn? Onderstaande code is een extract van unknwn.idl, regel 135 t/m 157:

IDL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
interface IClassFactory : IUnknown
{
    typedef [unique] IClassFactory * LPCLASSFACTORY;

    [local]
    HRESULT CreateInstance(
        [in, unique] IUnknown * pUnkOuter,
        [in] REFIID riid,
        [out, iid_is(riid)] void **ppvObject);

    [call_as(CreateInstance)]
    HRESULT RemoteCreateInstance(
        [in] REFIID riid,
        [out, iid_is(riid)] IUnknown ** ppvObject);

    [local]
    HRESULT LockServer(
        [in] BOOL fLock);

    [call_as(LockServer)]
    HRESULT __stdcall RemoteLockServer(
        [in] BOOL fLock);
}


Wat gaat hier nog fout?

"Kill one man, and you are a murderer. Kill millions of men, and you are a conqueror. Kill them all, and you are a god." -- Jean Rostand


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 17:14
Het aanroepen van COM functies vanuit C is extreem lastig, zelfs als de COM class gebouwd is met dezelfde compiler als de aanroepende code. Een COM-Delphi naar Cygwin-C interface is praktisch onmogelijk.

Wat veel haalbaarder is, is een interface laag. Met MSVC kun je een DLL bouwen, die een normale extern "C" interface aanbied, en deze implementeert met behulp van het Delphi COM object.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein

Pagina: 1