user18748: (Let's just skip the suggestions that it's the wrong idea and interrupts for a while...).
Is there a way to replace the digitalWrite() method (for example) so I can add something more to happen in there? But the following rules must be obeyed:

A call to digitalWrite(pin, value) must invoke the new method.
A call to digitalWrite(pin, value) from a different library included in my code (SD.h for example) must invoke the new method.
None of the Arduino files can be modified (I don't want to do it on every Arduino version upgrade).
Everything must be done in a header file that I can include to use the new function.

I have tried this and it works, but only in my code, not in external libraries that I include after this header:
#include <Arduino.h>

class PinsHook {
  public:
    static void digitalWriteHook(uint8_t pin, uint8_t value) {
      digitalWrite(pin, value);
      if (pin == 8) {
        Serial.print("Pin ");
        Serial.print(pin);
        Serial.print(" changed to ");
        Serial.println(value);
      }
    }
};

#define digitalWrite(pin, value) PinsHook::digitalWriteHook(pin, value)


user25690: Arduino uses the avr compiler to compile its standard library into a core.a file.
Due to the way the avr-gcc linker works and the order in which Arduino specifies the link order, you're able to "override" the behavior of core functions by copying the file that contains the method you want to alter into your project.

The compiler compiles a single high-level language file (C language,
  for example) into a single object module file. The linker (ld) can
  only work with object modules to link them together. Object modules
  are the smallest unit that the linker works with.
Typically, on the linker command line, you will specify a set of
  object modules (that has been previously compiled) and then a list of
  libraries, including the Standard C Library. The linker takes the set
  of object modules that you specify on the command line and links them
  together. Afterwards there will probably be a set of "undefined
  references". A reference is essentially a function call. An undefined
  reference is a function call, with no defined function to match the
  call.
The linker will then go through the libraries, in order, to match the
  undefined references with function definitions that are found in the
  libraries. If it finds the function that matches the call, the linker
  will then link in the object module in which the function is located.
  This part is important: the linker links in THE ENTIRE OBJECT MODULE
  in which the function is located. Remember, the linker knows nothing
  about the functions internal to an object module, other than symbol
  names (such as function names). The smallest unit the linker works
  with is object modules.
When there are no more undefined references, the linker has linked
  everything and is done and outputs the final application.
....
The linker will search libraries in the order that they appear on the
  command line. Whichever function is found first that matches the
  undefined reference, it will be linked in.

Arduino's linking occurs in this order:

Project Files
Libraries
core.a (Arduino std lib)

So, copying the file from the Arduino installation location (C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino) into your project and modifying it will result in it using your modified implementation. 
This will certainly over-ride it for any files in your project, and I believe it will also override it in any libraries you're using as well, so be careful with this approach.

user7508: Just throwing an idea. No time to test now.
Edit: I tested the solution below, and it works as expected,
provided both the __wrap_ and __real_digitalWrite() are declared
extern "C".
If you can convince the IDE to add extra options to the compile command
line, you could:

name __wrap_digitalWrite() your implementation of digitalWrite()
inside it, call __real_digitalWrite() when you want to get the
implementation from Arduino core
add -Wl,--wrap=digitalWrite to the compile command of the final
link step

Example wrapper:
extern "C" {
    void __wrap_digitalWrite(uint8_t, uint8_t);
    void __real_digitalWrite(uint8_t, uint8_t);
}

// Calls to digitalWrite() are diverted to this.
void __wrap_digitalWrite(uint8_t pin, uint8_t value)
{
    __real_digitalWrite(pin, value);  // call implementation from Arduino core
    if (pin == 8) {
        Serial.print(F("Pin 8 changed to "));
        Serial.println(value);
    }
}

Trying to put this inside a class won't help.
C.f. the man page of gnu ld.

user7856: Did you try with a C macro?
#define digitalWrite(a, b) \
(pre(), digitalWrite(a, b), post())

this evaluates to the retval of post()
you can omit either the pre() or the post() functions/macros.
This needs to be placed somewhere that is included whenever the header for digitalWrite is included, so that it can override it.
The only other alternative is to become creative with the library binary.
Or, just be reasonable and modify the source code.
It's specifically available so that people can modify it.
Wrt not repeating the modification every time there is a new Arduino release, that should be avoidable.
If you build the environment from the git sources, you can maintain your patch by merging/rebasing onto the master branch.

user4143: Not sure about the Arduino IDE (I don't have it installed right now) but using UECIDE it's as simple as defining a new digitalWrite function in your code.  When the whole shebang gets linked together the function in your code overrides the function in the libraries.
void setup() {
    pinMode(13, OUTPUT);
}

void loop() {
    digitalWrite(13, HIGH);
    delay(100);
    digitalWrite(13, LOW);
    delay(800);
}

void digitalWrite(int pin, int level) {
    // Not gonna do anything!
}

Comment out the digitalWrite function and the LED blinks.  Uncomment it and it doesn't blink any more.

18748: <p>(Let's just skip the suggestions that it's the wrong idea and interrupts for a while...).</p>

<p>Is there a way to replace the <code>digitalWrite()</code> method (for example) so I can add something more to happen in there? But the following rules must be obeyed:</p>

<ul>
<li>A call to <code>digitalWrite(pin, value)</code> must invoke the new method.</li>
<li>A call to <code>digitalWrite(pin, value)</code> from <strong>a different library</strong> included in my code (SD.h for example) must invoke the new method.</li>
<li>None of the Arduino files can be modified (I don't want to do it on every Arduino version upgrade).</li>
<li>Everything must be done in a header file that I can include to use the new function.</li>
</ul>

<p>I have tried this and it works, but only in my code, not in external libraries that I include after this header:</p>

<pre><code>#include &lt;Arduino.h&gt;

class PinsHook {
  public:
    static void digitalWriteHook(uint8_t pin, uint8_t value) {
      digitalWrite(pin, value);
      if (pin == 8) {
        Serial.print("Pin ");
        Serial.print(pin);
        Serial.print(" changed to ");
        Serial.println(value);
      }
    }
};

#define digitalWrite(pin, value) PinsHook::digitalWriteHook(pin, value)
</code></pre>
 25690: <p>Arduino uses the avr compiler to compile its standard library into a <code>core.a</code> file.
Due to the <a href="http://www.nongnu.org/avr-libc/user-manual/library.html" rel="nofollow noreferrer">way the avr-gcc linker works</a> and the order in which Arduino specifies the link order, you're able to "override" the behavior of core functions by copying the file that contains the method you want to alter into your project.</p>

<blockquote>
  <p>The compiler compiles a single high-level language file (C language,
  for example) into a single object module file. The linker (ld) can
  only work with object modules to link them together. Object modules
  are the smallest unit that the linker works with.</p>
  
  <p>Typically, on the linker command line, you will specify a set of
  object modules (that has been previously compiled) and then a list of
  libraries, including the Standard C Library. The linker takes the set
  of object modules that you specify on the command line and links them
  together. Afterwards there will probably be a set of "undefined
  references". A reference is essentially a function call. An undefined
  reference is a function call, with no defined function to match the
  call.</p>
  
  <p>The linker will then go through the libraries, in order, to match the
  undefined references with function definitions that are found in the
  libraries. If it finds the function that matches the call, the linker
  will then link in the object module in which the function is located.
  This part is important: the linker links in THE ENTIRE OBJECT MODULE
  in which the function is located. Remember, the linker knows nothing
  about the functions internal to an object module, other than symbol
  names (such as function names). The smallest unit the linker works
  with is object modules.</p>
  
  <p>When there are no more undefined references, the linker has linked
  everything and is done and outputs the final application.</p>
  
  <p>....</p>
  
  <p>The linker will search libraries in the order that they appear on the
  command line. Whichever function is found first that matches the
  undefined reference, it will be linked in.</p>
</blockquote>

<p>Arduino's linking occurs in this order:</p>

<ul>
<li>Project Files</li>
<li>Libraries</li>
<li>core.a (Arduino std lib)</li>
</ul>

<p>So, copying the file from the Arduino installation location (<code>C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino</code>) into your project and modifying it will result in it using your modified implementation. </p>

<p>This will certainly over-ride it for any files in your project, and <em>I believe</em> it will also override it in any libraries you're using as well, so be careful with this approach.</p>
 7508: <p><s>Just throwing an idea. No time to test now.</s></p>

<p><strong>Edit</strong>: I tested the solution below, and it works as expected,
provided both the <code>__wrap_</code> and <code>__real_digitalWrite()</code> are declared
<code>extern "C"</code>.</p>

<p>If you can convince the IDE to add extra options to the compile command
line, you could:</p>

<ol>
<li>name <code>__wrap_digitalWrite()</code> your implementation of <code>digitalWrite()</code></li>
<li>inside it, call <code>__real_digitalWrite()</code> when you want to get the
implementation from Arduino core</li>
<li>add <code>-Wl,--wrap=digitalWrite</code> to the compile command of the final
link step</li>
</ol>

<p>Example wrapper:</p>

<pre><code>extern "C" {
    void __wrap_digitalWrite(uint8_t, uint8_t);
    void __real_digitalWrite(uint8_t, uint8_t);
}

// Calls to digitalWrite() are diverted to this.
void __wrap_digitalWrite(uint8_t pin, uint8_t value)
{
    __real_digitalWrite(pin, value);  // call implementation from Arduino core
    if (pin == 8) {
        Serial.print(F("Pin 8 changed to "));
        Serial.println(value);
    }
}
</code></pre>

<p>Trying to put this inside a class won't help.</p>

<p>C.f. the <a href="https://linux.die.net/man/1/ld" rel="nofollow noreferrer">man page of gnu ld</a>.</p>
 7856: <p>Did you try with a C macro?</p>

<pre><code>#define digitalWrite(a, b) \
(pre(), digitalWrite(a, b), post())
</code></pre>

<p>this evaluates to the retval of <code>post()</code></p>

<p>you can omit either the <code>pre()</code> or the <code>post()</code> functions/macros.</p>

<p>This needs to be placed somewhere that is included whenever the header for digitalWrite is included, so that it can override it.</p>

<p>The only other alternative is to become creative with the library binary.</p>

<p>Or, just be reasonable and modify the source code.
It's specifically available so that people can modify it.</p>

<p>Wrt not repeating the modification every time there is a new Arduino release, that should be avoidable.
If you build the environment from the git sources, you can maintain your patch by merging/rebasing onto the master branch.</p>
 4143: <p>Not sure about the Arduino IDE (I don't have it installed right now) but using <a href="http://uecide.org" rel="nofollow">UECIDE</a> it's as simple as defining a new <code>digitalWrite</code> function in your code.  When the whole shebang gets linked together the function in your code overrides the function in the libraries.</p>

<pre><code>void setup() {
    pinMode(13, OUTPUT);
}

void loop() {
    digitalWrite(13, HIGH);
    delay(100);
    digitalWrite(13, LOW);
    delay(800);
}

void digitalWrite(int pin, int level) {
    // Not gonna do anything!
}
</code></pre>

<p>Comment out the digitalWrite function and the LED blinks.  Uncomment it and it doesn't blink any more.</p>
