linker error | undefined symbols

I have a C file for accessing the apple smc and I have the corresponding header file with my declarations in it but when I build my Xcode project I get the error:

"ld: Undefined symbols: _getTemperature, referenced from: _main in getsmc.o clang: error: linker comm"

#include <stdio.h>
#include <IOKit/IOKitLib.h>


    
    typedef struct {
        uint32_t datasize;
        uint32_t datatype;
        uint8_t data[32];
        
    } SMCVal_t;
    
    
    io_connect_t conn;
    
    kern_return_t openSMC(void) {
        
        kern_return_t result;
        kern_return_t service;
        io_iterator_t iterator;
        
        service = IOServiceGetMatchingServices(kIOMainPortDefault, IOServiceMatching("AppleSMC"), &iterator);
        if(service == 0) {
            printf("error: could not match dictionary");
            return 0;
        }
        result = IOServiceOpen(service, mach_task_self(), 0, &conn);
        IOObjectRelease(service);
        return 0;
    }
    
    kern_return_t closeSMC(void) {
        return IOServiceClose(conn);
        
    }
double getTemperature(char *key);
    
    kern_return_t readSMC(char *key, SMCVal_t *val) {
        kern_return_t result;
        uint32_t keyCode = *(uint32_t *)key;
        
        SMCVal_t inputStruct;
        SMCVal_t outputStruct;
        
        inputStruct.datasize = sizeof(SMCVal_t);
        inputStruct.datatype = 'I' << 24;            //a left shift operation. turning the I into an int by shifting the ASCII value 24 bits to the left
        
        inputStruct.data[0] = keyCode;
        result = IOConnectCallStructMethod(conn, 5, &inputStruct, sizeof(SMCVal_t), &outputStruct, (size_t*)&inputStruct.datasize);
        
        if (result == kIOReturnSuccess) {
            if (val -> datasize > 0) {
                if (val -> datatype == ('f' << 24 | 'l' << 16 | 't' << 8 )) {
                    float temp = *(float *)val -> data;
                    return temp;
                }
            }
        }
        return 0.0;
        
    }


    
    int main(void) {
        
        kern_return_t result;
        
        result = openSMC();
        
        if(result == kIOReturnSuccess) {
            double temp = getTemperature("TC0P");
            printf("temp: %.2f\n", temp);
            
            result = closeSMC();
        }
        return 0;
    }

Replies

You've declared getTemperature but not defined it. readSMC should return a kern_return_t but it is returning a double (0.0) or a float. I think you got readSMC mixed up with getTemperature.

While ssmith_c’s suggestions should help you fix the immediate issue, I want to caution you about the path you’re heading down…

WARNING When working with I/O Kit, understand that not everything you find in the I/O registry is considered API. You should look to the documentation and the symbolic constants in the headers as a guide as to what’s considered stable.

If you work with Apple’s services that are undocumented, it’s likely that your code will break in the future. Indeed, a bunch of code like this was broken by the switch to Apple silicon.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • Thank you for the head up. I'm definitely consulting documentation whenever I can but in all honesty I haven't been able to find much for what I am trying to accomplish with IOKit. I've mostly been consulting GitHub repos of apps that do something similar to what im trying to do as reference such as: https://github.com/beltex/SMCKit/blob/master/SMCKit/SMC.swift https://github.com/macmade/Hot

Add a Comment